diff --git a/.hgtags-top-repo b/.hgtags-top-repo index a5ae9ea7b47..e94921d7b41 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -444,3 +444,4 @@ a133a7d1007b1456bc62824382fd8ac93b45d329 jdk-10+17 b803e6cff41e72a1e6d8782e1ef7c25a6e3e5ee3 jdk-10+19 d2982a786f53814367698e63efe6349c9128e1db jdk-9+180 b656dea9398ef601f7fc08d1a5157a560e0ccbe0 jdk-9+181 +682e2a6df836f4731f92eb2ddcd467075047f6ea jdk-10+20 diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index e9aff624d73..443d119f7aa 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -187,6 +187,9 @@ TOOLCHAIN_MISC_CHECKS # Setup the JTReg Regression Test Harness. TOOLCHAIN_SETUP_JTREG +# Setup Jib dependency tool +TOOLCHAIN_SETUP_JIB + FLAGS_SETUP_INIT_FLAGS # Now we can test some aspects on the target using configure macros. @@ -220,7 +223,7 @@ BASIC_COMPILE_FIXPATH LIB_DETERMINE_DEPENDENCIES LIB_SETUP_LIBRARIES -# Hotspot setup depends on lib checks (AOT needs libelf). +# Hotspot setup depends on lib checks. HOTSPOT_SETUP_JVM_FEATURES diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index 6e64b5666ca..3340a0d5ed9 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -760,6 +760,19 @@ AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], [ FLAGS_SETUP_ABI_PROFILE + + # Optional POSIX functionality needed by the JVM + # + # Check if clock_gettime is available and in which library. This indicates + # availability of CLOCK_MONOTONIC for hotspot. But we don't need to link, so + # don't let it update LIBS. + save_LIBS="$LIBS" + AC_SEARCH_LIBS(clock_gettime, rt, [HAS_CLOCK_GETTIME=true], []) + if test "x$LIBS" = "x-lrt "; then + CLOCK_GETTIME_IN_LIBRT=true + fi + LIBS="$save_LIBS" + FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER([TARGET]) FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER([BUILD], [OPENJDK_BUILD_]) @@ -897,7 +910,7 @@ AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER], $2CFLAGS_JDK="[$]$2CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" $2CXXFLAGS_JDK="[$]$2CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" elif test "x$TOOLCHAIN_TYPE" = xxlc; then - $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_REENTRANT -D__STDC_FORMAT_MACROS" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_REENTRANT" $2CFLAGS_JDK="[$]$2CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" $2CXXFLAGS_JDK="[$]$2CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then @@ -962,6 +975,11 @@ AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER], fi fi + # Always enable optional macros for VM. + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D__STDC_FORMAT_MACROS" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D__STDC_LIMIT_MACROS" + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D__STDC_CONSTANT_MACROS" + # Setup target OS define. Use OS target name but in upper case. OPENJDK_$1_OS_UPPERCASE=`$ECHO $OPENJDK_$1_OS | $TR 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D$OPENJDK_$1_OS_UPPERCASE" @@ -981,6 +999,16 @@ AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER], $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -DDEBUG" fi + # Optional POSIX functionality needed by the VM + + if test "x$HAS_CLOCK_GETTIME" = "xtrue"; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DSUPPORTS_CLOCK_MONOTONIC" + if test "x$CLOCK_GETTIME_IN_LIBRT" = "xtrue"; then + $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DNEEDS_LIBRT" + fi + fi + + # Set some additional per-OS defines. if test "x$OPENJDK_$1_OS" = xlinux; then $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DLINUX" @@ -989,7 +1017,7 @@ AC_DEFUN([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK_HELPER], elif test "x$OPENJDK_$1_OS" = xsolaris; then $2JVM_CFLAGS="[$]$2JVM_CFLAGS -DSOLARIS" $2JVM_CFLAGS="[$]$2JVM_CFLAGS -template=no%extdef -features=no%split_init \ - -D_Crun_inline_placement -library=%none $PICFLAG -mt -features=no%except" + -D_Crun_inline_placement -library=stlport4 $PICFLAG -mt -features=no%except" elif test "x$OPENJDK_$1_OS" = xmacosx; then $2COMMON_CCXXFLAGS_JDK="[$]$2COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" $2JVM_CFLAGS="[$]$2JVM_CFLAGS -D_ALLBSD_SOURCE" diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 595463e823b..ba5847bae9d 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -663,8 +663,6 @@ JVM_FEATURES_core JVM_FEATURES_client JVM_FEATURES_server INCLUDE_GRAAL -ELF_LIBS -ELF_CFLAGS STLPORT_LIB LIBZIP_CAN_USE_MMAP LIBDL @@ -790,6 +788,7 @@ ARFLAGS COMPILER_BINDCMD_FILE_FLAG COMPILER_COMMAND_FILE_FLAG COMPILER_TARGET_BITS_FLAG +JIB_JAR JT_HOME JTREGEXE HOTSPOT_TOOLCHAIN_TYPE @@ -1182,6 +1181,7 @@ with_extra_ldflags with_toolchain_version with_build_devkit with_jtreg +with_jib with_abi_profile with_macosx_version_max enable_warnings_as_errors @@ -1219,9 +1219,6 @@ with_lcms with_dxsdk with_dxsdk_lib with_dxsdk_include -with_libelf -with_libelf_include -with_libelf_lib with_jvm_features with_jvm_interpreter enable_jtreg_failure_handler @@ -1351,8 +1348,6 @@ PNG_CFLAGS PNG_LIBS LCMS_CFLAGS LCMS_LIBS -ELF_CFLAGS -ELF_LIBS ICECC_CMD ICECC_CREATE_ENV ICECC_WRAPPER @@ -2130,6 +2125,7 @@ Optional Packages: dependent] --with-build-devkit Devkit to use for the build platform toolchain --with-jtreg Regression Test Harness [probed] + --with-jib Jib dependency management tool [not used] --with-abi-profile specify ABI profile for ARM builds (arm-vfp-sflt,arm-vfp-hflt,arm-sflt, armv5-vfp-sflt,armv6-vfp-hflt,arm64,aarch64) @@ -2186,11 +2182,6 @@ Optional Packages: compatibility and is ignored --with-dxsdk-include Deprecated. Option is kept for backwards compatibility and is ignored - --with-libelf specify prefix directory for the libelf package - (expecting the libraries under PATH/lib and the - headers under PATH/include) - --with-libelf-include specify directory for the libelf include files - --with-libelf-lib specify directory for the libelf library --with-jvm-features additional JVM features to enable (separated by comma), use '--help' to show possible values [none] --with-jvm-interpreter Deprecated. Option is kept for backwards @@ -2327,8 +2318,6 @@ Some influential environment variables: PNG_LIBS linker flags for PNG, overriding pkg-config LCMS_CFLAGS C compiler flags for LCMS, overriding pkg-config LCMS_LIBS linker flags for LCMS, overriding pkg-config - ELF_CFLAGS C compiler flags for ELF, overriding pkg-config - ELF_LIBS linker flags for ELF, overriding pkg-config ICECC_CMD Override default value for ICECC_CMD ICECC_CREATE_ENV Override default value for ICECC_CREATE_ENV @@ -4224,8 +4213,6 @@ apt_help() { PKGHANDLER_COMMAND="sudo apt-get install ccache" ;; dtrace) PKGHANDLER_COMMAND="sudo apt-get install systemtap-sdt-dev" ;; - elf) - PKGHANDLER_COMMAND="sudo apt-get install libelf-dev" ;; esac } @@ -4245,8 +4232,6 @@ yum_help() { PKGHANDLER_COMMAND="sudo yum install libXtst-devel libXt-devel libXrender-devel libXi-devel" ;; ccache) PKGHANDLER_COMMAND="sudo yum install ccache" ;; - elf) - PKGHANDLER_COMMAND="sudo yum install elfutils-libelf-devel" ;; esac } @@ -4516,7 +4501,7 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" # -# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2017, 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 @@ -4793,36 +4778,6 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" ################################################################################ -# -# 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. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -################################################################################ -# Setup libelf (ELF library) -################################################################################ - - ################################################################################ # Determine which libraries are needed for this configuration @@ -4961,7 +4916,7 @@ VALID_JVM_VARIANTS="server client minimal core zero zeroshark custom" # -# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2017, 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 @@ -5092,6 +5047,9 @@ TOOLCHAIN_MINIMUM_VERSION_xlc="" # Setup the JTReg Regression Test Harness. +# Setup the JIB dependency resolver + + # # Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -5193,7 +5151,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1500423205 +DATE_WHEN_GENERATED=1503411624 ############################################################################### # @@ -49524,6 +49482,41 @@ $as_echo "$as_me: The path of JT_HOME, which resolves as \"$path\", is invalid." +# Setup Jib dependency tool + + +# Check whether --with-jib was given. +if test "${with_jib+set}" = set; then : + withval=$with_jib; +fi + + + if test "x$with_jib" = xno || test "x$with_jib" = x; then + # jib disabled + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jib" >&5 +$as_echo_n "checking for jib... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + elif test "x$with_jib" = xyes; then + as_fn_error $? "Must supply a value to --with-jib" "$LINENO" 5 + else + JIB_HOME="${with_jib}" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for jib" >&5 +$as_echo_n "checking for jib... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${JIB_HOME}" >&5 +$as_echo "${JIB_HOME}" >&6; } + if test ! -d "${JIB_HOME}"; then + as_fn_error $? "--with-jib must be a directory" "$LINENO" 5 + fi + JIB_JAR=$(ls ${JIB_HOME}/lib/jib-*.jar) + if test ! -f "${JIB_JAR}"; then + as_fn_error $? "Could not find jib jar file in ${JIB_HOME}" "$LINENO" 5 + fi + fi + + + + # COMPILER_TARGET_BITS_FLAG : option for selecting 32- or 64-bit output # COMPILER_COMMAND_FILE_FLAG : option for passing a command file to the compiler @@ -51066,6 +51059,74 @@ $as_echo "$JDK_ARCH_ABI_PROP_NAME" >&6; } fi + # Optional POSIX functionality needed by the JVM + # + # Check if clock_gettime is available and in which library. This indicates + # availability of CLOCK_MONOTONIC for hotspot. But we don't need to link, so + # don't let it update LIBS. + save_LIBS="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing clock_gettime" >&5 +$as_echo_n "checking for library containing clock_gettime... " >&6; } +if ${ac_cv_search_clock_gettime+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +for ac_lib in '' rt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_clock_gettime=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_clock_gettime+:} false; then : + break +fi +done +if ${ac_cv_search_clock_gettime+:} false; then : + +else + ac_cv_search_clock_gettime=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_clock_gettime" >&5 +$as_echo "$ac_cv_search_clock_gettime" >&6; } +ac_res=$ac_cv_search_clock_gettime +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + HAS_CLOCK_GETTIME=true +fi + + if test "x$LIBS" = "x-lrt "; then + CLOCK_GETTIME_IN_LIBRT=true + fi + LIBS="$save_LIBS" + + # Special extras... if test "x$TOOLCHAIN_TYPE" = xsolstudio; then if test "x$OPENJDK_TARGET_CPU_ARCH" = "xsparc"; then @@ -51366,7 +51427,7 @@ $as_echo "$as_me: GCC >= 6 detected; adding ${NO_DELETE_NULL_POINTER_CHECKS_CFLA CFLAGS_JDK="$CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" CXXFLAGS_JDK="$CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" elif test "x$TOOLCHAIN_TYPE" = xxlc; then - JVM_CFLAGS="$JVM_CFLAGS -D_REENTRANT -D__STDC_FORMAT_MACROS" + JVM_CFLAGS="$JVM_CFLAGS -D_REENTRANT" CFLAGS_JDK="$CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" CXXFLAGS_JDK="$CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then @@ -51431,6 +51492,11 @@ $as_echo "$as_me: GCC >= 6 detected; adding ${NO_DELETE_NULL_POINTER_CHECKS_CFLA fi fi + # Always enable optional macros for VM. + JVM_CFLAGS="$JVM_CFLAGS -D__STDC_FORMAT_MACROS" + JVM_CFLAGS="$JVM_CFLAGS -D__STDC_LIMIT_MACROS" + JVM_CFLAGS="$JVM_CFLAGS -D__STDC_CONSTANT_MACROS" + # Setup target OS define. Use OS target name but in upper case. OPENJDK_TARGET_OS_UPPERCASE=`$ECHO $OPENJDK_TARGET_OS | $TR 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D$OPENJDK_TARGET_OS_UPPERCASE" @@ -51450,6 +51516,16 @@ $as_echo "$as_me: GCC >= 6 detected; adding ${NO_DELETE_NULL_POINTER_CHECKS_CFLA COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -DDEBUG" fi + # Optional POSIX functionality needed by the VM + + if test "x$HAS_CLOCK_GETTIME" = "xtrue"; then + JVM_CFLAGS="$JVM_CFLAGS -DSUPPORTS_CLOCK_MONOTONIC" + if test "x$CLOCK_GETTIME_IN_LIBRT" = "xtrue"; then + JVM_CFLAGS="$JVM_CFLAGS -DNEEDS_LIBRT" + fi + fi + + # Set some additional per-OS defines. if test "x$OPENJDK_TARGET_OS" = xlinux; then JVM_CFLAGS="$JVM_CFLAGS -DLINUX" @@ -51458,7 +51534,7 @@ $as_echo "$as_me: GCC >= 6 detected; adding ${NO_DELETE_NULL_POINTER_CHECKS_CFLA elif test "x$OPENJDK_TARGET_OS" = xsolaris; then JVM_CFLAGS="$JVM_CFLAGS -DSOLARIS" JVM_CFLAGS="$JVM_CFLAGS -template=no%extdef -features=no%split_init \ - -D_Crun_inline_placement -library=%none $PICFLAG -mt -features=no%except" + -D_Crun_inline_placement -library=stlport4 $PICFLAG -mt -features=no%except" elif test "x$OPENJDK_TARGET_OS" = xmacosx; then COMMON_CCXXFLAGS_JDK="$COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" JVM_CFLAGS="$JVM_CFLAGS -D_ALLBSD_SOURCE" @@ -52230,7 +52306,7 @@ $as_echo "$as_me: GCC >= 6 detected; adding ${NO_DELETE_NULL_POINTER_CHECKS_CFLA OPENJDK_BUILD_CFLAGS_JDK="$OPENJDK_BUILD_CFLAGS_JDK -xc99=%none -xCC -errshort=tags -Xa -v -mt -W0,-noglobal" OPENJDK_BUILD_CXXFLAGS_JDK="$OPENJDK_BUILD_CXXFLAGS_JDK -errtags=yes +w -mt -features=no%except -DCC_NOEX -norunpath -xnolib" elif test "x$TOOLCHAIN_TYPE" = xxlc; then - OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_REENTRANT -D__STDC_FORMAT_MACROS" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_REENTRANT" OPENJDK_BUILD_CFLAGS_JDK="$OPENJDK_BUILD_CFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" OPENJDK_BUILD_CXXFLAGS_JDK="$OPENJDK_BUILD_CXXFLAGS_JDK -D_GNU_SOURCE -D_REENTRANT -D_LARGEFILE64_SOURCE -DSTDC" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then @@ -52295,6 +52371,11 @@ $as_echo "$as_me: GCC >= 6 detected; adding ${NO_DELETE_NULL_POINTER_CHECKS_CFLA fi fi + # Always enable optional macros for VM. + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D__STDC_FORMAT_MACROS" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D__STDC_LIMIT_MACROS" + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D__STDC_CONSTANT_MACROS" + # Setup target OS define. Use OS target name but in upper case. OPENJDK_BUILD_OS_UPPERCASE=`$ECHO $OPENJDK_BUILD_OS | $TR 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D$OPENJDK_BUILD_OS_UPPERCASE" @@ -52314,6 +52395,16 @@ $as_echo "$as_me: GCC >= 6 detected; adding ${NO_DELETE_NULL_POINTER_CHECKS_CFLA OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -DDEBUG" fi + # Optional POSIX functionality needed by the VM + + if test "x$HAS_CLOCK_GETTIME" = "xtrue"; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DSUPPORTS_CLOCK_MONOTONIC" + if test "x$CLOCK_GETTIME_IN_LIBRT" = "xtrue"; then + OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DNEEDS_LIBRT" + fi + fi + + # Set some additional per-OS defines. if test "x$OPENJDK_BUILD_OS" = xlinux; then OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DLINUX" @@ -52322,7 +52413,7 @@ $as_echo "$as_me: GCC >= 6 detected; adding ${NO_DELETE_NULL_POINTER_CHECKS_CFLA elif test "x$OPENJDK_BUILD_OS" = xsolaris; then OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -DSOLARIS" OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -template=no%extdef -features=no%split_init \ - -D_Crun_inline_placement -library=%none $PICFLAG -mt -features=no%except" + -D_Crun_inline_placement -library=stlport4 $PICFLAG -mt -features=no%except" elif test "x$OPENJDK_BUILD_OS" = xmacosx; then OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK="$OPENJDK_BUILD_COMMON_CCXXFLAGS_JDK -D_ALLBSD_SOURCE -D_DARWIN_UNLIMITED_SELECT" OPENJDK_BUILD_JVM_CFLAGS="$OPENJDK_BUILD_JVM_CFLAGS -D_ALLBSD_SOURCE" @@ -53989,8 +54080,8 @@ $as_echo "no, forced" >&6; } fi if test "x$ENABLE_AOT" = "xtrue"; then - # Only enable AOT on linux-X64. - if test "x$OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU" = "xlinux-x86_64"; then + # Only enable AOT on X64 platforms. + if test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then if test -e "$HOTSPOT_TOPDIR/src/jdk.aot"; then if test -e "$HOTSPOT_TOPDIR/src/jdk.internal.vm.compiler"; then ENABLE_AOT="true" @@ -54009,7 +54100,7 @@ $as_echo "no, forced" >&6; } else ENABLE_AOT="false" if test "x$enable_aot" = "xyes"; then - as_fn_error $? "AOT is currently only supported on Linux-x86_64. Remove --enable-aot." "$LINENO" 5 + as_fn_error $? "AOT is currently only supported on x86_64. Remove --enable-aot." "$LINENO" 5 fi fi fi @@ -62526,7 +62617,7 @@ $as_echo "$FREETYPE_LIB_PATH" >&6; } if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_BASE_DIR/include" - POTENTIAL_FREETYPE_LIB_PATH="$FREETYPE_BASE_DIR/lib/x86_64-linux-gnu" + POTENTIAL_FREETYPE_LIB_PATH="$FREETYPE_BASE_DIR/lib/$OPENJDK_TARGET_CPU-linux-gnu" METHOD="well-known location" # Let's start with an optimistic view of the world :-) @@ -65499,279 +65590,6 @@ $as_echo "no, not found at $STLPORT_LIB" >&6; } -# Check whether --with-libelf was given. -if test "${with_libelf+set}" = set; then : - withval=$with_libelf; -fi - - -# Check whether --with-libelf-include was given. -if test "${with_libelf_include+set}" = set; then : - withval=$with_libelf_include; -fi - - -# Check whether --with-libelf-lib was given. -if test "${with_libelf_lib+set}" = set; then : - withval=$with_libelf_lib; -fi - - - if test "x$ENABLE_AOT" = xfalse; then - if (test "x${with_libelf}" != x && test "x${with_libelf}" != xno) || \ - (test "x${with_libelf_include}" != x && test "x${with_libelf_include}" != xno) || \ - (test "x${with_libelf_lib}" != x && test "x${with_libelf_lib}" != xno); then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libelf is not used, so --with-libelf[-*] is ignored" >&5 -$as_echo "$as_me: WARNING: libelf is not used, so --with-libelf[-*] is ignored" >&2;} - fi - LIBELF_CFLAGS= - LIBELF_LIBS= - else - LIBELF_FOUND=no - - if test "x${with_libelf}" = xno || test "x${with_libelf_include}" = xno || test "x${with_libelf_lib}" = xno; then - ENABLE_AOT="false" - if test "x${enable_aot}" = xyes; then - as_fn_error $? "libelf is explicitly disabled, cannot build AOT. Enable libelf or remove --enable-aot to disable AOT." "$LINENO" 5 - fi - else - if test "x${with_libelf}" != x; then - ELF_LIBS="-L${with_libelf}/lib -lelf" - ELF_CFLAGS="-I${with_libelf}/include" - LIBELF_FOUND=yes - fi - if test "x${with_libelf_include}" != x; then - ELF_CFLAGS="-I${with_libelf_include}" - LIBELF_FOUND=yes - fi - if test "x${with_libelf_lib}" != x; then - ELF_LIBS="-L${with_libelf_lib} -lelf" - LIBELF_FOUND=yes - fi - # Do not try pkg-config if we have a sysroot set. - if test "x$SYSROOT" = x; then - if test "x$LIBELF_FOUND" = xno; then - # Figure out ELF_CFLAGS and ELF_LIBS - -pkg_failed=no -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ELF" >&5 -$as_echo_n "checking for ELF... " >&6; } - -if test -n "$ELF_CFLAGS"; then - pkg_cv_ELF_CFLAGS="$ELF_CFLAGS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libelf\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libelf") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_ELF_CFLAGS=`$PKG_CONFIG --cflags "libelf" 2>/dev/null` -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi -if test -n "$ELF_LIBS"; then - pkg_cv_ELF_LIBS="$ELF_LIBS" - elif test -n "$PKG_CONFIG"; then - if test -n "$PKG_CONFIG" && \ - { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libelf\""; } >&5 - ($PKG_CONFIG --exists --print-errors "libelf") 2>&5 - ac_status=$? - $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; }; then - pkg_cv_ELF_LIBS=`$PKG_CONFIG --libs "libelf" 2>/dev/null` -else - pkg_failed=yes -fi - else - pkg_failed=untried -fi - - - -if test $pkg_failed = yes; then - -if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then - _pkg_short_errors_supported=yes -else - _pkg_short_errors_supported=no -fi - if test $_pkg_short_errors_supported = yes; then - ELF_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libelf" 2>&1` - else - ELF_PKG_ERRORS=`$PKG_CONFIG --print-errors "libelf" 2>&1` - fi - # Put the nasty error message in config.log where it belongs - echo "$ELF_PKG_ERRORS" >&5 - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - LIBELF_FOUND=no -elif test $pkg_failed = untried; then - LIBELF_FOUND=no -else - ELF_CFLAGS=$pkg_cv_ELF_CFLAGS - ELF_LIBS=$pkg_cv_ELF_LIBS - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - LIBELF_FOUND=yes -fi - fi - fi - if test "x$LIBELF_FOUND" = xno; then - for ac_header in libelf.h -do : - ac_fn_cxx_check_header_mongrel "$LINENO" "libelf.h" "ac_cv_header_libelf_h" "$ac_includes_default" -if test "x$ac_cv_header_libelf_h" = xyes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBELF_H 1 -_ACEOF - - LIBELF_FOUND=yes - ELF_CFLAGS= - ELF_LIBS=-lelf - -else - LIBELF_FOUND=no - -fi - -done - - fi - if test "x$LIBELF_FOUND" = xno; then - ENABLE_AOT="false" - - # Print a helpful message on how to acquire the necessary build dependency. - # elf is the help tag: freetype, cups, alsa etc - MISSING_DEPENDENCY=elf - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - cygwin_help $MISSING_DEPENDENCY - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - msys_help $MISSING_DEPENDENCY - else - PKGHANDLER_COMMAND= - - case $PKGHANDLER in - apt-get) - apt_help $MISSING_DEPENDENCY ;; - yum) - yum_help $MISSING_DEPENDENCY ;; - brew) - brew_help $MISSING_DEPENDENCY ;; - port) - port_help $MISSING_DEPENDENCY ;; - pkgutil) - pkgutil_help $MISSING_DEPENDENCY ;; - pkgadd) - pkgadd_help $MISSING_DEPENDENCY ;; - esac - - if test "x$PKGHANDLER_COMMAND" != x; then - HELP_MSG="You might be able to fix this by running '$PKGHANDLER_COMMAND'." - fi - fi - - if test "x${enable_aot}" = xyes; then - as_fn_error $? "libelf not found, cannot build AOT. Remove --enable-aot to disable AOT or: $HELP_MSG" "$LINENO" 5 - else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libelf not found, cannot build AOT. $HELP_MSG" >&5 -$as_echo "$as_me: WARNING: libelf not found, cannot build AOT. $HELP_MSG" >&2;} - fi - else - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libelf works" >&5 -$as_echo_n "checking if libelf works... " >&6; } - ac_ext=c -ac_cpp='$CPP $CPPFLAGS' -ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_c_compiler_gnu - - OLD_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $ELF_CFLAGS" - OLD_LIBS="$LIBS" - LIBS="$LIBS $ELF_LIBS" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -int -main () -{ - - elf_version(0); - return 0; - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - LIBELF_WORKS=yes -else - LIBELF_WORKS=no - -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext - CFLAGS="$OLD_CFLAGS" - LIBS="$OLD_LIBS" - ac_ext=cpp -ac_cpp='$CXXCPP $CPPFLAGS' -ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' -ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' -ac_compiler_gnu=$ac_cv_cxx_compiler_gnu - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBELF_WORKS" >&5 -$as_echo "$LIBELF_WORKS" >&6; } - - if test "x$LIBELF_WORKS" = xno; then - ENABLE_AOT="false" - - # Print a helpful message on how to acquire the necessary build dependency. - # elf is the help tag: freetype, cups, alsa etc - MISSING_DEPENDENCY=elf - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - cygwin_help $MISSING_DEPENDENCY - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - msys_help $MISSING_DEPENDENCY - else - PKGHANDLER_COMMAND= - - case $PKGHANDLER in - apt-get) - apt_help $MISSING_DEPENDENCY ;; - yum) - yum_help $MISSING_DEPENDENCY ;; - brew) - brew_help $MISSING_DEPENDENCY ;; - port) - port_help $MISSING_DEPENDENCY ;; - pkgutil) - pkgutil_help $MISSING_DEPENDENCY ;; - pkgadd) - pkgadd_help $MISSING_DEPENDENCY ;; - esac - - if test "x$PKGHANDLER_COMMAND" != x; then - HELP_MSG="You might be able to fix this by running '$PKGHANDLER_COMMAND'." - fi - fi - - if test "x$enable_aot" = "xyes"; then - as_fn_error $? "Found libelf but could not link and compile with it. Remove --enable-aot to disable AOT or: $HELP_MSG" "$LINENO" 5 - else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Found libelf but could not link and compile with it. $HELP_MSG" >&5 -$as_echo "$as_me: WARNING: Found libelf but could not link and compile with it. $HELP_MSG" >&2;} - fi - fi - fi - fi - fi @@ -65783,14 +65601,7 @@ $as_echo "$as_me: WARNING: Found libelf but could not link and compile with it. - - - - - - - -# Hotspot setup depends on lib checks (AOT needs libelf). +# Hotspot setup depends on lib checks. # The user can in some cases supply additional jvm features. For the custom diff --git a/common/autoconf/help.m4 b/common/autoconf/help.m4 index 1a313e62236..8e4cf4da567 100644 --- a/common/autoconf/help.m4 +++ b/common/autoconf/help.m4 @@ -123,8 +123,6 @@ apt_help() { PKGHANDLER_COMMAND="sudo apt-get install ccache" ;; dtrace) PKGHANDLER_COMMAND="sudo apt-get install systemtap-sdt-dev" ;; - elf) - PKGHANDLER_COMMAND="sudo apt-get install libelf-dev" ;; esac } @@ -144,8 +142,6 @@ yum_help() { PKGHANDLER_COMMAND="sudo yum install libXtst-devel libXt-devel libXrender-devel libXi-devel" ;; ccache) PKGHANDLER_COMMAND="sudo yum install ccache" ;; - elf) - PKGHANDLER_COMMAND="sudo yum install elfutils-libelf-devel" ;; esac } diff --git a/common/autoconf/hotspot.m4 b/common/autoconf/hotspot.m4 index acf2a5fe185..99803d1770b 100644 --- a/common/autoconf/hotspot.m4 +++ b/common/autoconf/hotspot.m4 @@ -212,8 +212,8 @@ AC_DEFUN_ONCE([HOTSPOT_ENABLE_DISABLE_AOT], fi if test "x$ENABLE_AOT" = "xtrue"; then - # Only enable AOT on linux-X64. - if test "x$OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU" = "xlinux-x86_64"; then + # Only enable AOT on X64 platforms. + if test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then if test -e "$HOTSPOT_TOPDIR/src/jdk.aot"; then if test -e "$HOTSPOT_TOPDIR/src/jdk.internal.vm.compiler"; then ENABLE_AOT="true" @@ -232,7 +232,7 @@ AC_DEFUN_ONCE([HOTSPOT_ENABLE_DISABLE_AOT], else ENABLE_AOT="false" if test "x$enable_aot" = "xyes"; then - AC_MSG_ERROR([AOT is currently only supported on Linux-x86_64. Remove --enable-aot.]) + AC_MSG_ERROR([AOT is currently only supported on x86_64. Remove --enable-aot.]) fi fi fi diff --git a/common/autoconf/lib-elf.m4 b/common/autoconf/lib-elf.m4 deleted file mode 100644 index 9d5230b6968..00000000000 --- a/common/autoconf/lib-elf.m4 +++ /dev/null @@ -1,129 +0,0 @@ -# -# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -################################################################################ -# Setup libelf (ELF library) -################################################################################ -AC_DEFUN_ONCE([LIB_SETUP_LIBELF], -[ - AC_ARG_WITH(libelf, [AS_HELP_STRING([--with-libelf], - [specify prefix directory for the libelf package - (expecting the libraries under PATH/lib and the headers under PATH/include)])]) - AC_ARG_WITH(libelf-include, [AS_HELP_STRING([--with-libelf-include], - [specify directory for the libelf include files])]) - AC_ARG_WITH(libelf-lib, [AS_HELP_STRING([--with-libelf-lib], - [specify directory for the libelf library])]) - - if test "x$ENABLE_AOT" = xfalse; then - if (test "x${with_libelf}" != x && test "x${with_libelf}" != xno) || \ - (test "x${with_libelf_include}" != x && test "x${with_libelf_include}" != xno) || \ - (test "x${with_libelf_lib}" != x && test "x${with_libelf_lib}" != xno); then - AC_MSG_WARN([[libelf is not used, so --with-libelf[-*] is ignored]]) - fi - LIBELF_CFLAGS= - LIBELF_LIBS= - else - LIBELF_FOUND=no - - if test "x${with_libelf}" = xno || test "x${with_libelf_include}" = xno || test "x${with_libelf_lib}" = xno; then - ENABLE_AOT="false" - if test "x${enable_aot}" = xyes; then - AC_MSG_ERROR([libelf is explicitly disabled, cannot build AOT. Enable libelf or remove --enable-aot to disable AOT.]) - fi - else - if test "x${with_libelf}" != x; then - ELF_LIBS="-L${with_libelf}/lib -lelf" - ELF_CFLAGS="-I${with_libelf}/include" - LIBELF_FOUND=yes - fi - if test "x${with_libelf_include}" != x; then - ELF_CFLAGS="-I${with_libelf_include}" - LIBELF_FOUND=yes - fi - if test "x${with_libelf_lib}" != x; then - ELF_LIBS="-L${with_libelf_lib} -lelf" - LIBELF_FOUND=yes - fi - # Do not try pkg-config if we have a sysroot set. - if test "x$SYSROOT" = x; then - if test "x$LIBELF_FOUND" = xno; then - # Figure out ELF_CFLAGS and ELF_LIBS - PKG_CHECK_MODULES([ELF], [libelf], [LIBELF_FOUND=yes], [LIBELF_FOUND=no]) - fi - fi - if test "x$LIBELF_FOUND" = xno; then - AC_CHECK_HEADERS([libelf.h], - [ - LIBELF_FOUND=yes - ELF_CFLAGS= - ELF_LIBS=-lelf - ], - [LIBELF_FOUND=no] - ) - fi - if test "x$LIBELF_FOUND" = xno; then - ENABLE_AOT="false" - HELP_MSG_MISSING_DEPENDENCY([elf]) - if test "x${enable_aot}" = xyes; then - AC_MSG_ERROR([libelf not found, cannot build AOT. Remove --enable-aot to disable AOT or: $HELP_MSG]) - else - AC_MSG_WARN([libelf not found, cannot build AOT. $HELP_MSG]) - fi - else - AC_MSG_CHECKING([if libelf works]) - AC_LANG_PUSH(C) - OLD_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS $ELF_CFLAGS" - OLD_LIBS="$LIBS" - LIBS="$LIBS $ELF_LIBS" - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [ - elf_version(0); - return 0; - ])], - [LIBELF_WORKS=yes], - [LIBELF_WORKS=no] - ) - CFLAGS="$OLD_CFLAGS" - LIBS="$OLD_LIBS" - AC_LANG_POP(C) - AC_MSG_RESULT([$LIBELF_WORKS]) - - if test "x$LIBELF_WORKS" = xno; then - ENABLE_AOT="false" - HELP_MSG_MISSING_DEPENDENCY([elf]) - if test "x$enable_aot" = "xyes"; then - AC_MSG_ERROR([Found libelf but could not link and compile with it. Remove --enable-aot to disable AOT or: $HELP_MSG]) - else - AC_MSG_WARN([Found libelf but could not link and compile with it. $HELP_MSG]) - fi - fi - fi - fi - fi - - AC_SUBST(ELF_CFLAGS) - AC_SUBST(ELF_LIBS) -]) diff --git a/common/autoconf/lib-freetype.m4 b/common/autoconf/lib-freetype.m4 index 17dd726e54c..a7985bb34b0 100644 --- a/common/autoconf/lib-freetype.m4 +++ b/common/autoconf/lib-freetype.m4 @@ -366,7 +366,7 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE], if test "x$FOUND_FREETYPE" != xyes; then FREETYPE_BASE_DIR="$SYSROOT/usr" if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then - LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib/x86_64-linux-gnu], [well-known location]) + LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib/$OPENJDK_TARGET_CPU-linux-gnu], [well-known location]) else LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib/i386-linux-gnu], [well-known location]) if test "x$FOUND_FREETYPE" != xyes; then diff --git a/common/autoconf/libraries.m4 b/common/autoconf/libraries.m4 index bd5a40a7eaf..02f3239132b 100644 --- a/common/autoconf/libraries.m4 +++ b/common/autoconf/libraries.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,6 @@ m4_include([lib-ffi.m4]) m4_include([lib-freetype.m4]) m4_include([lib-std.m4]) m4_include([lib-x11.m4]) -m4_include([lib-elf.m4]) ################################################################################ # Determine which libraries are needed for this configuration @@ -91,7 +90,6 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES], LIB_SETUP_BUNDLED_LIBS LIB_SETUP_MISC_LIBS LIB_SETUP_SOLARIS_STLPORT - LIB_SETUP_LIBELF ]) ################################################################################ diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 7f2e0f97336..72e28cf5905 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -690,6 +690,7 @@ SETFILE:=@SETFILE@ XATTR:=@XATTR@ JT_HOME:=@JT_HOME@ JTREGEXE:=@JTREGEXE@ +JIB_JAR:=@JIB_JAR@ XCODEBUILD=@XCODEBUILD@ DTRACE := @DTRACE@ FIXPATH:=@FIXPATH@ @@ -774,9 +775,6 @@ USE_EXTERNAL_LIBPNG:=@USE_EXTERNAL_LIBPNG@ PNG_LIBS:=@PNG_LIBS@ PNG_CFLAGS:=@PNG_CFLAGS@ -ELF_CFLAGS:=@ELF_CFLAGS@ -ELF_LIBS:=@ELF_LIBS@ - #################################################### # # Misc diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index 37f99fff82b..e97a8ec1d49 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2017, 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 @@ -1005,3 +1005,31 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_JTREG], AC_SUBST(JT_HOME) AC_SUBST(JTREGEXE) ]) + +# Setup the JIB dependency resolver +AC_DEFUN_ONCE([TOOLCHAIN_SETUP_JIB], +[ + AC_ARG_WITH(jib, [AS_HELP_STRING([--with-jib], + [Jib dependency management tool @<:@not used@:>@])]) + + if test "x$with_jib" = xno || test "x$with_jib" = x; then + # jib disabled + AC_MSG_CHECKING([for jib]) + AC_MSG_RESULT(no) + elif test "x$with_jib" = xyes; then + AC_MSG_ERROR([Must supply a value to --with-jib]) + else + JIB_HOME="${with_jib}" + AC_MSG_CHECKING([for jib]) + AC_MSG_RESULT(${JIB_HOME}) + if test ! -d "${JIB_HOME}"; then + AC_MSG_ERROR([--with-jib must be a directory]) + fi + JIB_JAR=$(ls ${JIB_HOME}/lib/jib-*.jar) + if test ! -f "${JIB_JAR}"; then + AC_MSG_ERROR([Could not find jib jar file in ${JIB_HOME}]) + fi + fi + + AC_SUBST(JIB_JAR) +]) diff --git a/common/conf/jib-profiles.js b/common/conf/jib-profiles.js index 36d3e8735c9..361938be105 100644 --- a/common/conf/jib-profiles.js +++ b/common/conf/jib-profiles.js @@ -237,7 +237,7 @@ var getJibProfilesCommon = function (input, data) { // These are the base setttings for all the main build profiles. common.main_profile_base = { - dependencies: ["boot_jdk", "gnumake", "jtreg"], + dependencies: ["boot_jdk", "gnumake", "jtreg", "jib"], default_make_targets: ["product-bundles", "test-bundles"], configure_args: concat(["--enable-jtreg-failure-handler"], versionArgs(input, common)) @@ -590,7 +590,7 @@ var getJibProfilesProfiles = function (input, common, data) { "run-test-jprt": { target_os: input.build_os, target_cpu: input.build_cpu, - dependencies: [ "jtreg", "gnumake", "boot_jdk" ], + dependencies: [ "jtreg", "gnumake", "boot_jdk", "devkit", "jib" ], labels: "test", environment: { "JT_JAVA": common.boot_jdk_home @@ -600,7 +600,7 @@ var getJibProfilesProfiles = function (input, common, data) { "run-test": { target_os: input.build_os, target_cpu: input.build_cpu, - dependencies: [ "jtreg", "gnumake", "boot_jdk" ], + dependencies: [ "jtreg", "gnumake", "boot_jdk", "devkit", "jib" ], labels: "test", environment: { "JT_JAVA": common.boot_jdk_home @@ -619,7 +619,7 @@ var getJibProfilesProfiles = function (input, common, data) { target_os: input.build_os, target_cpu: input.build_cpu, src: "src.conf", - dependencies: [ "jtreg", "gnumake", "boot_jdk", testedProfile + ".jdk", + dependencies: [ "jtreg", "gnumake", "boot_jdk", "jib", testedProfile + ".jdk", testedProfile + ".test", "src.full" ], work_dir: input.get("src.full", "install_path") + "/test", @@ -974,7 +974,7 @@ var getJibProfilesDependencies = function (input, common) { jtreg: { server: "javare", revision: "4.2", - build_number: "b07", + build_number: "b08", checksum_file: "MD5_VALUES", file: "jtreg_bin-4.2.zip", environment_name: "JT_HOME", @@ -1023,8 +1023,26 @@ var getJibProfilesDependencies = function (input, common) { configure_args: "PANDOC=" + input.get("pandoc", "install_path") + "/pandoc/pandoc", environment_path: input.get("pandoc", "install_path") + "/pandoc" }, + // This adds java jib as a dependency for the test artifacts resolver + jib: { + organization: "com.oracle.java.jib", + ext: "zip", + classifier: "distribution", + revision: "3.0-SNAPSHOT", + environment_name: "JIB_JAR", + environment_value: input.get("jib", "install_path") + + "/jib-3.0-SNAPSHOT-distribution/lib/jib-3.0-SNAPSHOT.jar" + } }; + // Need to add a value for the Visual Studio tools variable to make + // jaot be able to pick up the Visual Studio linker in testing. + if (input.target_os == "windows") { + dependencies.devkit.environment = { + VS120COMNTOOLS: input.get("devkit", "install_path") + "/Common7/Tools" + }; + } + return dependencies; }; diff --git a/common/doc/building.html b/common/doc/building.html index 48ddbc1c6f4..3b34dbd235e 100644 --- a/common/doc/building.html +++ b/common/doc/building.html @@ -58,7 +58,6 @@
  • X11
  • ALSA
  • libffi
  • -
  • libelf
  • Other Tooling Requirements
    • GNU Make
    • @@ -469,13 +468,6 @@ tar -xzf freetype-2.5.3.tar.gz
    • To install on an rpm-based Linux, try running sudo yum install libffi-devel.

    Use --with-libffi=<path> if configure does not properly locate your libffi files.

    -

    libelf

    -

    libelf from the elfutils project is required when building the AOT feature of Hotspot.

    -
      -
    • To install on an apt-based Linux, try running sudo apt-get install libelf-dev.
    • -
    • To install on an rpm-based Linux, try running sudo yum install elfutils-libelf-devel.
    • -
    -

    Use --with-libelf=<path> if configure does not properly locate your libelf files.

    Other Tooling Requirements

    GNU Make

    OpenJDK requires GNU Make. No other flavors of make are supported.

    @@ -537,7 +529,6 @@ tar -xzf freetype-2.5.3.tar.gz
  • --with-x=<path> - Set the path to X11
  • --with-alsa=<path> - Set the path to ALSA
  • --with-libffi=<path> - Set the path to libffi
  • -
  • --with-libelf=<path> - Set the path to libelf
  • --with-jtreg=<path> - Set the path to JTReg. See Running Tests
  • Certain third-party libraries used by OpenJDK (libjpeg, giflib, libpng, lcms and zlib) are included in the OpenJDK repository. The default behavior of the OpenJDK build is to use this version of these libraries, but they might be replaced by an external version. To do so, specify system as the <source> option in these arguments. (The default is bundled).

    diff --git a/common/doc/building.md b/common/doc/building.md index 101d041103b..5767ee6f64c 100644 --- a/common/doc/building.md +++ b/common/doc/building.md @@ -648,19 +648,6 @@ Hotspot. Use `--with-libffi=` if `configure` does not properly locate your libffi files. -### libelf - -libelf from the [elfutils project](http://sourceware.org/elfutils) is required -when building the AOT feature of Hotspot. - - * To install on an apt-based Linux, try running `sudo apt-get install - libelf-dev`. - * To install on an rpm-based Linux, try running `sudo yum install - elfutils-libelf-devel`. - -Use `--with-libelf=` if `configure` does not properly locate your libelf -files. - ## Other Tooling Requirements ### GNU Make @@ -813,7 +800,6 @@ features, use `bash configure --help=short` instead.) * `--with-x=` - Set the path to [X11](#x11) * `--with-alsa=` - Set the path to [ALSA](#alsa) * `--with-libffi=` - Set the path to [libffi](#libffi) - * `--with-libelf=` - Set the path to [libelf](#libelf) * `--with-jtreg=` - Set the path to JTReg. See [Running Tests]( #running-tests) diff --git a/corba/.hgtags b/corba/.hgtags index 3955e7c2528..c1ceb6e6be3 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -444,3 +444,4 @@ a923b3f30e7bddb4f960059ddfc7978fc63e2e6e jdk-10+18 28488561cfbcfa4d0d9c489e8afe0155f4231360 jdk-10+19 6ce6cb8ff41c71c49f23b15e0f0468aca5d52b17 jdk-9+180 ba71941ad9dba53b8fffb30602ef673eee88696c jdk-9+181 +7a54ec280513a33e49e60546c0cf9ca573925a43 jdk-10+20 diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 282c0940830..005d486ea58 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -604,3 +604,4 @@ c9d3317623d48da3327232c81e3f8cfc0d29d888 jdk-10+18 33b74e13c1457f36041addb8b850831f81ca6e9f jdk-10+19 d7baadc223e790c08bc69bf7e553bce65b4e7e40 jdk-9+180 4a443796f6f57842d6a0434ac27ca3d1033ccc20 jdk-9+181 +e93ed1a092409351c90b3a76d80b9aa8b44d5e6a jdk-10+20 diff --git a/hotspot/make/CompileTools.gmk b/hotspot/make/CompileTools.gmk index c80632226cf..309d9c9aaf6 100644 --- a/hotspot/make/CompileTools.gmk +++ b/hotspot/make/CompileTools.gmk @@ -47,11 +47,10 @@ ifeq ($(INCLUDE_GRAAL), true) $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_MATCH_PROCESSOR, \ SETUP := GENERATE_OLDBYTECODE, \ SRC := \ - $(SRC_DIR)/org.graalvm.compiler.common/src \ + $(SRC_DIR)/org.graalvm.word/src \ $(SRC_DIR)/org.graalvm.compiler.core/src \ $(SRC_DIR)/org.graalvm.compiler.core.common/src \ $(SRC_DIR)/org.graalvm.compiler.core.match.processor/src \ - $(SRC_DIR)/org.graalvm.compiler.api.collections/src \ $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \ $(SRC_DIR)/org.graalvm.compiler.asm/src \ $(SRC_DIR)/org.graalvm.compiler.bytecode/src \ @@ -68,6 +67,7 @@ ifeq ($(INCLUDE_GRAAL), true) $(SRC_DIR)/org.graalvm.compiler.phases.common/src \ $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \ $(SRC_DIR)/org.graalvm.compiler.virtual/src \ + $(SRC_DIR)/org.graalvm.util/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.meta/src \ @@ -102,6 +102,7 @@ ifeq ($(INCLUDE_GRAAL), true) SRC := \ $(SRC_DIR)/org.graalvm.compiler.options/src \ $(SRC_DIR)/org.graalvm.compiler.options.processor/src \ + $(SRC_DIR)/org.graalvm.util/src \ , \ BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.options.processor, \ JAR := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.options.processor.jar, \ @@ -114,9 +115,8 @@ ifeq ($(INCLUDE_GRAAL), true) $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_REPLACEMENTS_VERIFIER, \ SETUP := GENERATE_OLDBYTECODE, \ SRC := \ - $(SRC_DIR)/org.graalvm.compiler.common/src \ + $(SRC_DIR)/org.graalvm.word/src \ $(SRC_DIR)/org.graalvm.compiler.replacements.verifier/src \ - $(SRC_DIR)/org.graalvm.compiler.api.collections/src \ $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \ $(SRC_DIR)/org.graalvm.compiler.code/src \ $(SRC_DIR)/org.graalvm.compiler.core.common/src \ @@ -125,6 +125,7 @@ ifeq ($(INCLUDE_GRAAL), true) $(SRC_DIR)/org.graalvm.compiler.nodeinfo/src \ $(SRC_DIR)/org.graalvm.compiler.options/src \ $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \ + $(SRC_DIR)/org.graalvm.util/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \ $(VM_CI_SRC_DIR)/jdk.vm.ci.meta/src \ diff --git a/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk b/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk index a8e60309b1c..623430abab6 100644 --- a/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk +++ b/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk @@ -37,7 +37,6 @@ SRC_DIR := $(HOTSPOT_TOPDIR)/src/$(MODULE)/share/classes PROC_SRC_SUBDIRS := \ org.graalvm.compiler.code \ - org.graalvm.compiler.common \ org.graalvm.compiler.core \ org.graalvm.compiler.core.aarch64 \ org.graalvm.compiler.core.amd64 \ diff --git a/hotspot/make/gensrc/GensrcAdlc.gmk b/hotspot/make/gensrc/GensrcAdlc.gmk index 3153476960b..ef3b1cf9a12 100644 --- a/hotspot/make/gensrc/GensrcAdlc.gmk +++ b/hotspot/make/gensrc/GensrcAdlc.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2017, 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 @@ -73,7 +73,7 @@ ifeq ($(call check-jvm-feature, compiler2), true) OUTPUT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/adlc, \ PROGRAM := adlc, \ DEBUG_SYMBOLS := false, \ - DISABLED_WARNINGS_clang := parentheses tautological-compare, \ + DISABLED_WARNINGS_clang := tautological-compare, \ DISABLED_WARNINGS_solstudio := notemsource, \ )) diff --git a/hotspot/make/lib/CompileDtracePostJvm.gmk b/hotspot/make/lib/CompileDtracePostJvm.gmk index 77a4e30f4d9..1051cafe8dd 100644 --- a/hotspot/make/lib/CompileDtracePostJvm.gmk +++ b/hotspot/make/lib/CompileDtracePostJvm.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2017, 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 @@ -52,7 +52,7 @@ ifeq ($(call check-jvm-feature, dtrace), true) CXX := $(BUILD_CXX), \ LDEXE := $(BUILD_CXX), \ generateJvmOffsets.cpp_CXXFLAGS := $(JVM_CFLAGS) -mt -xnolib -norunpath, \ - generateJvmOffsetsMain.c_CFLAGS := -library=%none -mt -m64 -norunpath -z nodefs, \ + generateJvmOffsetsMain.c_CFLAGS := -mt -m64 -norunpath -z nodefs, \ LDFLAGS := -m64, \ LIBS := -lc, \ OBJECT_DIR := $(JVM_VARIANT_OUTPUTDIR)/tools/dtrace-gen-offsets/objs, \ diff --git a/hotspot/make/lib/CompileGtest.gmk b/hotspot/make/lib/CompileGtest.gmk index 29209432f41..10e3f14de0d 100644 --- a/hotspot/make/lib/CompileGtest.gmk +++ b/hotspot/make/lib/CompileGtest.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2016, 2017, 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 @@ -52,7 +52,8 @@ else $(call create-mapfile) endif -# Disabling switch warning for clang because of test source. +# Disabling undef, switch, format-nonliteral and tautological-undefined-compare +# warnings for clang because of test source. # Note: On AIX, the gtest test classes linked into the libjvm.so push the TOC # size beyond 64k, so we need to link with bigtoc. However, this means that diff --git a/hotspot/make/lib/CompileJvm.gmk b/hotspot/make/lib/CompileJvm.gmk index 4eb2cbc1013..d5ecb2555f3 100644 --- a/hotspot/make/lib/CompileJvm.gmk +++ b/hotspot/make/lib/CompileJvm.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2017, 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 @@ -69,6 +69,7 @@ JVM_CFLAGS_TARGET_DEFINES += \ -DTARGET_ARCH_$(HOTSPOT_TARGET_CPU_ARCH) \ -DINCLUDE_SUFFIX_OS=_$(HOTSPOT_TARGET_OS) \ -DINCLUDE_SUFFIX_CPU=_$(HOTSPOT_TARGET_CPU_ARCH) \ + -DINCLUDE_SUFFIX_COMPILER=_$(HOTSPOT_TOOLCHAIN_TYPE) \ -DTARGET_COMPILER_$(HOTSPOT_TOOLCHAIN_TYPE) \ -D$(HOTSPOT_TARGET_CPU_DEFINE) \ -DHOTSPOT_LIB_ARCH='"$(OPENJDK_TARGET_CPU_LEGACY_LIB)"' \ @@ -217,9 +218,7 @@ $(eval $(call SetupNativeCompilation, BUILD_LIBJVM, \ CFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \ CXXFLAGS_DEBUG_SYMBOLS := $(JVM_CFLAGS_SYMBOLS), \ vm_version.cpp_CXXFLAGS := $(CFLAGS_VM_VERSION), \ - DISABLED_WARNINGS_clang := delete-non-virtual-dtor dynamic-class-memaccess \ - empty-body format logical-op-parentheses parentheses \ - parentheses-equality switch tautological-compare, \ + DISABLED_WARNINGS_clang := tautological-compare, \ DISABLED_WARNINGS_xlc := 1540-0216 1540-0198 1540-1090 1540-1639 \ 1540-1088 1500-010, \ ASFLAGS := $(JVM_ASFLAGS), \ diff --git a/hotspot/make/lib/Lib-jdk.aot.gmk b/hotspot/make/lib/Lib-jdk.aot.gmk deleted file mode 100644 index d799fa45286..00000000000 --- a/hotspot/make/lib/Lib-jdk.aot.gmk +++ /dev/null @@ -1,53 +0,0 @@ -# -# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -include $(SPEC) -include NativeCompilation.gmk - -$(eval $(call IncludeCustomExtension, hotspot, lib/Lib-jdk.aot.gmk)) - -############################################################################## -# Build libjelfshim only when AOT is enabled. -ifeq ($(ENABLE_AOT), true) - JELFSHIM_NAME := jelfshim - - $(eval $(call SetupNativeCompilation, BUILD_LIBJELFSHIM, \ - TOOLCHAIN := TOOLCHAIN_DEFAULT, \ - OPTIMIZATION := LOW, \ - LIBRARY := $(JELFSHIM_NAME), \ - OUTPUT_DIR := $(call FindLibDirForModule, $(MODULE)), \ - SRC := $(HOTSPOT_TOPDIR)/src/jdk.aot/unix/native/libjelfshim, \ - CFLAGS := $(CFLAGS_JDKLIB) $(ELF_CFLAGS) \ - -DAOT_VERSION_STRING='"$(VERSION_STRING)"' \ - -I$(SUPPORT_OUTPUTDIR)/headers/$(MODULE), \ - LDFLAGS := $(LDFLAGS_JDKLIB), \ - OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/lib$(JELFSHIM_NAME), \ - LIBS := $(ELF_LIBS) $(LIBS_JDKLIB), \ - )) - - TARGETS += $(BUILD_LIBJELFSHIM) -endif - -############################################################################## diff --git a/hotspot/make/test/JtregNative.gmk b/hotspot/make/test/JtregNative.gmk index 19faa10ad3d..3f1d3fd46be 100644 --- a/hotspot/make/test/JtregNative.gmk +++ b/hotspot/make/test/JtregNative.gmk @@ -35,12 +35,17 @@ include $(SPEC) include MakeBase.gmk include TestFilesCompilation.gmk +$(eval $(call IncludeCustomExtension, hotspot, test/JtregNative.gmk)) + ################################################################################ # Targets for building the native tests themselves. ################################################################################ # Add more directories here when needed. -BUILD_HOTSPOT_JTREG_NATIVE_SRC := \ +BUILD_HOTSPOT_JTREG_NATIVE_SRC += \ + $(HOTSPOT_TOPDIR)/test/gc/g1/TestJNIWeakG1 \ + $(HOTSPOT_TOPDIR)/test/gc/stress/gclocker \ + $(HOTSPOT_TOPDIR)/test/gc/cslocker \ $(HOTSPOT_TOPDIR)/test/native_sanity \ $(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \ $(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \ @@ -53,8 +58,10 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \ $(HOTSPOT_TOPDIR)/test/runtime/modules/getModuleJNI \ $(HOTSPOT_TOPDIR)/test/runtime/SameObject \ $(HOTSPOT_TOPDIR)/test/runtime/BoolReturn \ + $(HOTSPOT_TOPDIR)/test/runtime/noClassDefFoundMsg \ $(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \ $(HOTSPOT_TOPDIR)/test/compiler/calls \ + $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/GetOwnedMonitorInfo \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/GetNamedModule \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/IsModifiableModule \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/AddModuleReads \ @@ -66,6 +73,7 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/ModuleAwareAgents/ClassLoadPrepare \ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/ModuleAwareAgents/ThreadStart \ + $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/StartPhase/AllowedFunctions \ # # Add conditional directories here when needed. @@ -85,6 +93,7 @@ endif ifeq ($(TOOLCHAIN_TYPE), solstudio) BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liboverflow := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libSimpleClassFileLoadHook := -lc + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libGetOwnedMonitorInfoTest := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libGetNamedModuleTest := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libIsModifiableModuleTest := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libAddModuleReadsTest := -lc @@ -93,6 +102,7 @@ ifeq ($(TOOLCHAIN_TYPE), solstudio) BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAClassFileLoadHook := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAClassLoadPrepare := -lc BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAThreadStart := -lc + BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libAllowedFunctions := -lc endif ifeq ($(OPENJDK_TARGET_OS), linux) diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad index cd2174a67c3..a4a8be37022 100644 --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. // Copyright (c) 2014, Red Hat Inc. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // @@ -3564,7 +3564,7 @@ const int Matcher::min_vector_size(const BasicType bt) { } // Vector ideal reg. -const int Matcher::vector_ideal_reg(int len) { +const uint Matcher::vector_ideal_reg(int len) { switch(len) { case 8: return Op_VecD; case 16: return Op_VecX; @@ -3573,7 +3573,7 @@ const int Matcher::vector_ideal_reg(int len) { return 0; } -const int Matcher::vector_shift_count_ideal_reg(int size) { +const uint Matcher::vector_shift_count_ideal_reg(int size) { return Op_VecX; } @@ -5218,7 +5218,7 @@ frame %{ // ppc port uses 0 but we definitely need to allow for fixed_slots // which folds in the space used for monitors return_addr(STACK - 2 + - round_to((Compile::current()->in_preserve_stack_slots() + + align_up((Compile::current()->in_preserve_stack_slots() + Compile::current()->fixed_slots()), stack_alignment_in_slots())); @@ -5343,6 +5343,17 @@ operand immI_M1() interface(CONST_INTER); %} +// Shift values for add/sub extension shift +operand immIExt() +%{ + predicate(0 <= n->get_int() && (n->get_int() <= 4)); + match(ConI); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + operand immI_le_4() %{ predicate(n->get_int() <= 4); @@ -5423,6 +5434,16 @@ operand immI_56() interface(CONST_INTER); %} +operand immI_63() +%{ + predicate(n->get_int() == 63); + match(ConI); + + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + operand immI_64() %{ predicate(n->get_int() == 64); @@ -5453,20 +5474,10 @@ operand immI_65535() interface(CONST_INTER); %} -operand immL_63() -%{ - predicate(n->get_int() == 63); - match(ConI); - - op_cost(0); - format %{ %} - interface(CONST_INTER); -%} - operand immL_255() %{ - predicate(n->get_int() == 255); - match(ConI); + predicate(n->get_long() == 255L); + match(ConL); op_cost(0); format %{ %} @@ -10951,7 +10962,7 @@ instruct negI_reg(iRegINoSp dst, iRegIorL2I src, immI0 zero, rFlagsReg cr) %{ // Long Negation -instruct negL_reg(iRegLNoSp dst, iRegIorL2I src, immL0 zero, rFlagsReg cr) %{ +instruct negL_reg(iRegLNoSp dst, iRegL src, immL0 zero, rFlagsReg cr) %{ match(Set dst (SubL zero src)); ins_cost(INSN_COST); @@ -11146,7 +11157,7 @@ instruct divL(iRegLNoSp dst, iRegL src1, iRegL src2) %{ ins_pipe(ldiv_reg_reg); %} -instruct signExtractL(iRegLNoSp dst, iRegL src1, immL_63 div1, immL_63 div2) %{ +instruct signExtractL(iRegLNoSp dst, iRegL src1, immI_63 div1, immI_63 div2) %{ match(Set dst (URShiftL (RShiftL src1 div1) div2)); ins_cost(INSN_COST); format %{ "lsr $dst, $src1, $div1" %} @@ -11156,7 +11167,7 @@ instruct signExtractL(iRegLNoSp dst, iRegL src1, immL_63 div1, immL_63 div2) %{ ins_pipe(ialu_reg_shift); %} -instruct div2RoundL(iRegLNoSp dst, iRegL src, immL_63 div1, immL_63 div2) %{ +instruct div2RoundL(iRegLNoSp dst, iRegL src, immI_63 div1, immI_63 div2) %{ match(Set dst (AddL src (URShiftL (RShiftL src div1) div2))); ins_cost(INSN_COST); format %{ "add $dst, $src, $div1" %} @@ -12789,7 +12800,7 @@ instruct AddExtI(iRegLNoSp dst, iRegL src1, iRegIorL2I src2, rFlagsReg cr) %{ match(Set dst (AddL src1 (ConvI2L src2))); ins_cost(INSN_COST); - format %{ "add $dst, $src1, sxtw $src2" %} + format %{ "add $dst, $src1, $src2, sxtw" %} ins_encode %{ __ add(as_Register($dst$$reg), as_Register($src1$$reg), @@ -12802,7 +12813,7 @@ instruct SubExtI(iRegLNoSp dst, iRegL src1, iRegIorL2I src2, rFlagsReg cr) %{ match(Set dst (SubL src1 (ConvI2L src2))); ins_cost(INSN_COST); - format %{ "sub $dst, $src1, sxtw $src2" %} + format %{ "sub $dst, $src1, $src2, sxtw" %} ins_encode %{ __ sub(as_Register($dst$$reg), as_Register($src1$$reg), @@ -12816,7 +12827,7 @@ instruct AddExtI_sxth(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_16 l %{ match(Set dst (AddI src1 (RShiftI (LShiftI src2 lshift) rshift))); ins_cost(INSN_COST); - format %{ "add $dst, $src1, sxth $src2" %} + format %{ "add $dst, $src1, $src2, sxth" %} ins_encode %{ __ add(as_Register($dst$$reg), as_Register($src1$$reg), @@ -12829,7 +12840,7 @@ instruct AddExtI_sxtb(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_24 l %{ match(Set dst (AddI src1 (RShiftI (LShiftI src2 lshift) rshift))); ins_cost(INSN_COST); - format %{ "add $dst, $src1, sxtb $src2" %} + format %{ "add $dst, $src1, $src2, sxtb" %} ins_encode %{ __ add(as_Register($dst$$reg), as_Register($src1$$reg), @@ -12842,7 +12853,7 @@ instruct AddExtI_uxtb(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_24 l %{ match(Set dst (AddI src1 (URShiftI (LShiftI src2 lshift) rshift))); ins_cost(INSN_COST); - format %{ "add $dst, $src1, uxtb $src2" %} + format %{ "add $dst, $src1, $src2, uxtb" %} ins_encode %{ __ add(as_Register($dst$$reg), as_Register($src1$$reg), @@ -12855,7 +12866,7 @@ instruct AddExtL_sxth(iRegLNoSp dst, iRegL src1, iRegL src2, immI_48 lshift, imm %{ match(Set dst (AddL src1 (RShiftL (LShiftL src2 lshift) rshift))); ins_cost(INSN_COST); - format %{ "add $dst, $src1, sxth $src2" %} + format %{ "add $dst, $src1, $src2, sxth" %} ins_encode %{ __ add(as_Register($dst$$reg), as_Register($src1$$reg), @@ -12868,7 +12879,7 @@ instruct AddExtL_sxtw(iRegLNoSp dst, iRegL src1, iRegL src2, immI_32 lshift, imm %{ match(Set dst (AddL src1 (RShiftL (LShiftL src2 lshift) rshift))); ins_cost(INSN_COST); - format %{ "add $dst, $src1, sxtw $src2" %} + format %{ "add $dst, $src1, $src2, sxtw" %} ins_encode %{ __ add(as_Register($dst$$reg), as_Register($src1$$reg), @@ -12881,7 +12892,7 @@ instruct AddExtL_sxtb(iRegLNoSp dst, iRegL src1, iRegL src2, immI_56 lshift, imm %{ match(Set dst (AddL src1 (RShiftL (LShiftL src2 lshift) rshift))); ins_cost(INSN_COST); - format %{ "add $dst, $src1, sxtb $src2" %} + format %{ "add $dst, $src1, $src2, sxtb" %} ins_encode %{ __ add(as_Register($dst$$reg), as_Register($src1$$reg), @@ -12894,7 +12905,7 @@ instruct AddExtL_uxtb(iRegLNoSp dst, iRegL src1, iRegL src2, immI_56 lshift, imm %{ match(Set dst (AddL src1 (URShiftL (LShiftL src2 lshift) rshift))); ins_cost(INSN_COST); - format %{ "add $dst, $src1, uxtb $src2" %} + format %{ "add $dst, $src1, $src2, uxtb" %} ins_encode %{ __ add(as_Register($dst$$reg), as_Register($src1$$reg), @@ -13034,6 +13045,294 @@ instruct SubExtL_uxtw_and(iRegLNoSp dst, iRegL src1, iRegL src2, immL_4294967295 ins_pipe(ialu_reg_reg); %} + +instruct AddExtL_sxtb_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immIExt lshift2, immI_56 lshift1, immI_56 rshift1, rFlagsReg cr) +%{ + match(Set dst (AddL src1 (LShiftL (RShiftL (LShiftL src2 lshift1) rshift1) lshift2))); + ins_cost(1.9 * INSN_COST); + format %{ "add $dst, $src1, $src2, sxtb #lshift2" %} + + ins_encode %{ + __ add(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::sxtb, ($lshift2$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct AddExtL_sxth_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immIExt lshift2, immI_48 lshift1, immI_48 rshift1, rFlagsReg cr) +%{ + match(Set dst (AddL src1 (LShiftL (RShiftL (LShiftL src2 lshift1) rshift1) lshift2))); + ins_cost(1.9 * INSN_COST); + format %{ "add $dst, $src1, $src2, sxth #lshift2" %} + + ins_encode %{ + __ add(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::sxth, ($lshift2$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct AddExtL_sxtw_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immIExt lshift2, immI_32 lshift1, immI_32 rshift1, rFlagsReg cr) +%{ + match(Set dst (AddL src1 (LShiftL (RShiftL (LShiftL src2 lshift1) rshift1) lshift2))); + ins_cost(1.9 * INSN_COST); + format %{ "add $dst, $src1, $src2, sxtw #lshift2" %} + + ins_encode %{ + __ add(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::sxtw, ($lshift2$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct SubExtL_sxtb_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immIExt lshift2, immI_56 lshift1, immI_56 rshift1, rFlagsReg cr) +%{ + match(Set dst (SubL src1 (LShiftL (RShiftL (LShiftL src2 lshift1) rshift1) lshift2))); + ins_cost(1.9 * INSN_COST); + format %{ "sub $dst, $src1, $src2, sxtb #lshift2" %} + + ins_encode %{ + __ sub(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::sxtb, ($lshift2$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct SubExtL_sxth_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immIExt lshift2, immI_48 lshift1, immI_48 rshift1, rFlagsReg cr) +%{ + match(Set dst (SubL src1 (LShiftL (RShiftL (LShiftL src2 lshift1) rshift1) lshift2))); + ins_cost(1.9 * INSN_COST); + format %{ "sub $dst, $src1, $src2, sxth #lshift2" %} + + ins_encode %{ + __ sub(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::sxth, ($lshift2$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct SubExtL_sxtw_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immIExt lshift2, immI_32 lshift1, immI_32 rshift1, rFlagsReg cr) +%{ + match(Set dst (SubL src1 (LShiftL (RShiftL (LShiftL src2 lshift1) rshift1) lshift2))); + ins_cost(1.9 * INSN_COST); + format %{ "sub $dst, $src1, $src2, sxtw #lshift2" %} + + ins_encode %{ + __ sub(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::sxtw, ($lshift2$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct AddExtI_sxtb_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immIExt lshift2, immI_24 lshift1, immI_24 rshift1, rFlagsReg cr) +%{ + match(Set dst (AddI src1 (LShiftI (RShiftI (LShiftI src2 lshift1) rshift1) lshift2))); + ins_cost(1.9 * INSN_COST); + format %{ "addw $dst, $src1, $src2, sxtb #lshift2" %} + + ins_encode %{ + __ addw(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::sxtb, ($lshift2$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct AddExtI_sxth_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immIExt lshift2, immI_16 lshift1, immI_16 rshift1, rFlagsReg cr) +%{ + match(Set dst (AddI src1 (LShiftI (RShiftI (LShiftI src2 lshift1) rshift1) lshift2))); + ins_cost(1.9 * INSN_COST); + format %{ "addw $dst, $src1, $src2, sxth #lshift2" %} + + ins_encode %{ + __ addw(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::sxth, ($lshift2$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct SubExtI_sxtb_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immIExt lshift2, immI_24 lshift1, immI_24 rshift1, rFlagsReg cr) +%{ + match(Set dst (SubI src1 (LShiftI (RShiftI (LShiftI src2 lshift1) rshift1) lshift2))); + ins_cost(1.9 * INSN_COST); + format %{ "subw $dst, $src1, $src2, sxtb #lshift2" %} + + ins_encode %{ + __ subw(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::sxtb, ($lshift2$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct SubExtI_sxth_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immIExt lshift2, immI_16 lshift1, immI_16 rshift1, rFlagsReg cr) +%{ + match(Set dst (SubI src1 (LShiftI (RShiftI (LShiftI src2 lshift1) rshift1) lshift2))); + ins_cost(1.9 * INSN_COST); + format %{ "subw $dst, $src1, $src2, sxth #lshift2" %} + + ins_encode %{ + __ subw(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::sxth, ($lshift2$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + + +instruct AddExtI_shift(iRegLNoSp dst, iRegL src1, iRegIorL2I src2, immIExt lshift, rFlagsReg cr) +%{ + match(Set dst (AddL src1 (LShiftL (ConvI2L src2) lshift))); + ins_cost(1.9 * INSN_COST); + format %{ "add $dst, $src1, $src2, sxtw #lshift" %} + + ins_encode %{ + __ add(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::sxtw, ($lshift$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%}; + +instruct SubExtI_shift(iRegLNoSp dst, iRegL src1, iRegIorL2I src2, immIExt lshift, rFlagsReg cr) +%{ + match(Set dst (SubL src1 (LShiftL (ConvI2L src2) lshift))); + ins_cost(1.9 * INSN_COST); + format %{ "sub $dst, $src1, $src2, sxtw #lshift" %} + + ins_encode %{ + __ sub(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::sxtw, ($lshift$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%}; + + +instruct AddExtL_uxtb_and_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immL_255 mask, immIExt lshift, rFlagsReg cr) +%{ + match(Set dst (AddL src1 (LShiftL (AndL src2 mask) lshift))); + ins_cost(1.9 * INSN_COST); + format %{ "add $dst, $src1, $src2, uxtb #lshift" %} + + ins_encode %{ + __ add(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::uxtb, ($lshift$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct AddExtL_uxth_and_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immL_65535 mask, immIExt lshift, rFlagsReg cr) +%{ + match(Set dst (AddL src1 (LShiftL (AndL src2 mask) lshift))); + ins_cost(1.9 * INSN_COST); + format %{ "add $dst, $src1, $src2, uxth #lshift" %} + + ins_encode %{ + __ add(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::uxth, ($lshift$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct AddExtL_uxtw_and_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immL_4294967295 mask, immIExt lshift, rFlagsReg cr) +%{ + match(Set dst (AddL src1 (LShiftL (AndL src2 mask) lshift))); + ins_cost(1.9 * INSN_COST); + format %{ "add $dst, $src1, $src2, uxtw #lshift" %} + + ins_encode %{ + __ add(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::uxtw, ($lshift$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct SubExtL_uxtb_and_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immL_255 mask, immIExt lshift, rFlagsReg cr) +%{ + match(Set dst (SubL src1 (LShiftL (AndL src2 mask) lshift))); + ins_cost(1.9 * INSN_COST); + format %{ "sub $dst, $src1, $src2, uxtb #lshift" %} + + ins_encode %{ + __ sub(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::uxtb, ($lshift$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct SubExtL_uxth_and_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immL_65535 mask, immIExt lshift, rFlagsReg cr) +%{ + match(Set dst (SubL src1 (LShiftL (AndL src2 mask) lshift))); + ins_cost(1.9 * INSN_COST); + format %{ "sub $dst, $src1, $src2, uxth #lshift" %} + + ins_encode %{ + __ sub(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::uxth, ($lshift$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct SubExtL_uxtw_and_shift(iRegLNoSp dst, iRegL src1, iRegL src2, immL_4294967295 mask, immIExt lshift, rFlagsReg cr) +%{ + match(Set dst (SubL src1 (LShiftL (AndL src2 mask) lshift))); + ins_cost(1.9 * INSN_COST); + format %{ "sub $dst, $src1, $src2, uxtw #lshift" %} + + ins_encode %{ + __ sub(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::uxtw, ($lshift$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct AddExtI_uxtb_and_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_255 mask, immIExt lshift, rFlagsReg cr) +%{ + match(Set dst (AddI src1 (LShiftI (AndI src2 mask) lshift))); + ins_cost(1.9 * INSN_COST); + format %{ "addw $dst, $src1, $src2, uxtb #lshift" %} + + ins_encode %{ + __ addw(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::uxtb, ($lshift$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct AddExtI_uxth_and_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_65535 mask, immIExt lshift, rFlagsReg cr) +%{ + match(Set dst (AddI src1 (LShiftI (AndI src2 mask) lshift))); + ins_cost(1.9 * INSN_COST); + format %{ "addw $dst, $src1, $src2, uxth #lshift" %} + + ins_encode %{ + __ addw(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::uxth, ($lshift$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct SubExtI_uxtb_and_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_255 mask, immIExt lshift, rFlagsReg cr) +%{ + match(Set dst (SubI src1 (LShiftI (AndI src2 mask) lshift))); + ins_cost(1.9 * INSN_COST); + format %{ "subw $dst, $src1, $src2, uxtb #lshift" %} + + ins_encode %{ + __ subw(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::uxtb, ($lshift$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} + +instruct SubExtI_uxth_and_shift(iRegINoSp dst, iRegIorL2I src1, iRegIorL2I src2, immI_65535 mask, immIExt lshift, rFlagsReg cr) +%{ + match(Set dst (SubI src1 (LShiftI (AndI src2 mask) lshift))); + ins_cost(1.9 * INSN_COST); + format %{ "subw $dst, $src1, $src2, uxth #lshift" %} + + ins_encode %{ + __ subw(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::uxth, ($lshift$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%} // END This section of the file is automatically generated. Do not edit -------------- // ============================================================================ @@ -15443,9 +15742,9 @@ instruct ShouldNotReachHere() %{ format %{ "ShouldNotReachHere" %} ins_encode %{ - // TODO - // implement proper trap call here - __ brk(999); + // +1 so NativeInstruction::is_sigill_zombie_not_entrant() doesn't + // return true + __ dpcs1(0xdead + 1); %} ins_pipe(pipe_class_default); @@ -15803,6 +16102,16 @@ instruct array_equalsC(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, ins_pipe(pipe_class_memory); %} +instruct has_negatives(iRegP_R1 ary1, iRegI_R2 len, iRegI_R0 result, rFlagsReg cr) +%{ + match(Set result (HasNegatives ary1 len)); + effect(USE_KILL ary1, USE_KILL len, KILL cr); + format %{ "has negatives byte[] $ary1,$len -> $result" %} + ins_encode %{ + __ has_negatives($ary1$$Register, $len$$Register, $result$$Register); + %} + ins_pipe( pipe_slow ); +%} // fast char[] to byte[] compression instruct string_compress(iRegP_R2 src, iRegP_R1 dst, iRegI_R3 len, @@ -16833,6 +17142,48 @@ instruct vmla4I(vecX dst, vecX src1, vecX src2) ins_pipe(vmla128); %} +// dst + src1 * src2 +instruct vmla2F(vecD dst, vecD src1, vecD src2) %{ + predicate(UseFMA && n->as_Vector()->length() == 2); + match(Set dst (FmaVF dst (Binary src1 src2))); + format %{ "fmla $dst,$src1,$src2\t# vector (2S)" %} + ins_cost(INSN_COST); + ins_encode %{ + __ fmla(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp64); +%} + +// dst + src1 * src2 +instruct vmla4F(vecX dst, vecX src1, vecX src2) %{ + predicate(UseFMA && n->as_Vector()->length() == 4); + match(Set dst (FmaVF dst (Binary src1 src2))); + format %{ "fmla $dst,$src1,$src2\t# vector (4S)" %} + ins_cost(INSN_COST); + ins_encode %{ + __ fmla(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + +// dst + src1 * src2 +instruct vmla2D(vecX dst, vecX src1, vecX src2) %{ + predicate(UseFMA && n->as_Vector()->length() == 2); + match(Set dst (FmaVD dst (Binary src1 src2))); + format %{ "fmla $dst,$src1,$src2\t# vector (2D)" %} + ins_cost(INSN_COST); + ins_encode %{ + __ fmla(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + // --------------------------------- MLS -------------------------------------- instruct vmls4S(vecD dst, vecD src1, vecD src2) @@ -16892,6 +17243,51 @@ instruct vmls4I(vecX dst, vecX src1, vecX src2) ins_pipe(vmla128); %} +// dst - src1 * src2 +instruct vmls2F(vecD dst, vecD src1, vecD src2) %{ + predicate(UseFMA && n->as_Vector()->length() == 2); + match(Set dst (FmaVF dst (Binary (NegVF src1) src2))); + match(Set dst (FmaVF dst (Binary src1 (NegVF src2)))); + format %{ "fmls $dst,$src1,$src2\t# vector (2S)" %} + ins_cost(INSN_COST); + ins_encode %{ + __ fmls(as_FloatRegister($dst$$reg), __ T2S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp64); +%} + +// dst - src1 * src2 +instruct vmls4F(vecX dst, vecX src1, vecX src2) %{ + predicate(UseFMA && n->as_Vector()->length() == 4); + match(Set dst (FmaVF dst (Binary (NegVF src1) src2))); + match(Set dst (FmaVF dst (Binary src1 (NegVF src2)))); + format %{ "fmls $dst,$src1,$src2\t# vector (4S)" %} + ins_cost(INSN_COST); + ins_encode %{ + __ fmls(as_FloatRegister($dst$$reg), __ T4S, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + +// dst - src1 * src2 +instruct vmls2D(vecX dst, vecX src1, vecX src2) %{ + predicate(UseFMA && n->as_Vector()->length() == 2); + match(Set dst (FmaVD dst (Binary (NegVD src1) src2))); + match(Set dst (FmaVD dst (Binary src1 (NegVD src2)))); + format %{ "fmls $dst,$src1,$src2\t# vector (2D)" %} + ins_cost(INSN_COST); + ins_encode %{ + __ fmls(as_FloatRegister($dst$$reg), __ T2D, + as_FloatRegister($src1$$reg), + as_FloatRegister($src2$$reg)); + %} + ins_pipe(vmuldiv_fp128); +%} + // --------------------------------- DIV -------------------------------------- instruct vdiv2F(vecD dst, vecD src1, vecD src2) diff --git a/hotspot/src/cpu/aarch64/vm/aarch64_ad.m4 b/hotspot/src/cpu/aarch64/vm/aarch64_ad.m4 index cc2e748dd66..b2a4d379eb9 100644 --- a/hotspot/src/cpu/aarch64/vm/aarch64_ad.m4 +++ b/hotspot/src/cpu/aarch64/vm/aarch64_ad.m4 @@ -268,21 +268,21 @@ instruct $2$1_rReg(iReg$1NoSp dst, iReg$1 src, iRegI shift, rFlagsReg cr) ins_pipe(ialu_reg_reg_vshift); %}')dnl define(ROL_INSN, ` -instruct $3$1_rReg_Var_C$2(iRegLNoSp dst, iRegL src, iRegI shift, immI$2 c$2, rFlagsReg cr) +instruct $3$1_rReg_Var_C$2(iReg$1NoSp dst, iReg$1 src, iRegI shift, immI$2 c$2, rFlagsReg cr) %{ match(Set dst (Or$1 (LShift$1 src shift) (URShift$1 src (SubI c$2 shift)))); expand %{ - $3L_rReg(dst, src, shift, cr); + $3$1_rReg(dst, src, shift, cr); %} %}')dnl define(ROR_INSN, ` -instruct $3$1_rReg_Var_C$2(iRegLNoSp dst, iRegL src, iRegI shift, immI$2 c$2, rFlagsReg cr) +instruct $3$1_rReg_Var_C$2(iReg$1NoSp dst, iReg$1 src, iRegI shift, immI$2 c$2, rFlagsReg cr) %{ match(Set dst (Or$1 (URShift$1 src shift) (LShift$1 src (SubI c$2 shift)))); expand %{ - $3L_rReg(dst, src, shift, cr); + $3$1_rReg(dst, src, shift, cr); %} %}')dnl ROL_EXPAND(L, rol, rorv) @@ -305,7 +305,7 @@ instruct $3Ext$1(iReg$2NoSp dst, iReg$2`'ORL2I($2) src1, iReg$1`'ORL2I($1) src2, %{ match(Set dst ($3$2 src1 (ConvI2L src2))); ins_cost(INSN_COST); - format %{ "$4 $dst, $src1, $5 $src2" %} + format %{ "$4 $dst, $src1, $src2, $5" %} ins_encode %{ __ $4(as_Register($dst$$reg), as_Register($src1$$reg), @@ -321,7 +321,7 @@ instruct $3Ext$1_$6(iReg$1NoSp dst, iReg$1`'ORL2I($1) src1, iReg$1`'ORL2I($1) sr %{ match(Set dst ($3$1 src1 EXTEND($1, $4, src2, lshift, rshift))); ins_cost(INSN_COST); - format %{ "$5 $dst, $src1, $6 $src2" %} + format %{ "$5 $dst, $src1, $src2, $6" %} ins_encode %{ __ $5(as_Register($dst$$reg), as_Register($src1$$reg), @@ -363,5 +363,82 @@ ADD_SUB_ZERO_EXTEND(I,65535,Sub,subw,uxth) ADD_SUB_ZERO_EXTEND(L,255,Sub,sub,uxtb) ADD_SUB_ZERO_EXTEND(L,65535,Sub,sub,uxth) ADD_SUB_ZERO_EXTEND(L,4294967295,Sub,sub,uxtw) +dnl +dnl ADD_SUB_ZERO_EXTEND_SHIFT(mode, size, add node, insn, ext type) +define(`ADD_SUB_EXTENDED_SHIFT', ` +instruct $3Ext$1_$6_shift(iReg$1NoSp dst, iReg$1`'ORL2I($1) src1, iReg$1`'ORL2I($1) src2, immIExt lshift2, immI_`'eval($7-$2) lshift1, immI_`'eval($7-$2) rshift1, rFlagsReg cr) +%{ + match(Set dst ($3$1 src1 (LShift$1 EXTEND($1, $4, src2, lshift1, rshift1) lshift2))); + ins_cost(1.9 * INSN_COST); + format %{ "$5 $dst, $src1, $src2, $6 #lshift2" %} + ins_encode %{ + __ $5(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::$6, ($lshift2$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%}') +dnl $1 $2 $3 $4 $5 $6 $7 +ADD_SUB_EXTENDED_SHIFT(L,8,Add,RShift,add,sxtb,64) +ADD_SUB_EXTENDED_SHIFT(L,16,Add,RShift,add,sxth,64) +ADD_SUB_EXTENDED_SHIFT(L,32,Add,RShift,add,sxtw,64) +dnl +ADD_SUB_EXTENDED_SHIFT(L,8,Sub,RShift,sub,sxtb,64) +ADD_SUB_EXTENDED_SHIFT(L,16,Sub,RShift,sub,sxth,64) +ADD_SUB_EXTENDED_SHIFT(L,32,Sub,RShift,sub,sxtw,64) +dnl +ADD_SUB_EXTENDED_SHIFT(I,8,Add,RShift,addw,sxtb,32) +ADD_SUB_EXTENDED_SHIFT(I,16,Add,RShift,addw,sxth,32) +dnl +ADD_SUB_EXTENDED_SHIFT(I,8,Sub,RShift,subw,sxtb,32) +ADD_SUB_EXTENDED_SHIFT(I,16,Sub,RShift,subw,sxth,32) +dnl +dnl ADD_SUB_CONV_SHIFT(mode, add node, insn, ext type) +define(`ADD_SUB_CONV_SHIFT', ` +instruct $2ExtI_shift(iReg$1NoSp dst, iReg$1`'ORL2I($1) src1, iRegIorL2I src2, immIExt lshift, rFlagsReg cr) +%{ + match(Set dst ($2$1 src1 (LShiftL (ConvI2L src2) lshift))); + ins_cost(1.9 * INSN_COST); + format %{ "$3 $dst, $src1, $src2, $4 #lshift" %} + + ins_encode %{ + __ $3(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::$4, ($lshift$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%}') +dnl +ADD_SUB_CONV_SHIFT(L,Add,add,sxtw); +ADD_SUB_CONV_SHIFT(L,Sub,sub,sxtw); +dnl +dnl ADD_SUB_ZERO_EXTEND(mode, size, add node, insn, ext type) +define(`ADD_SUB_ZERO_EXTEND_SHIFT', ` +instruct $3Ext$1_$5_and_shift(iReg$1NoSp dst, iReg$1`'ORL2I($1) src1, iReg$1`'ORL2I($1) src2, imm$1_$2 mask, immIExt lshift, rFlagsReg cr) +%{ + match(Set dst ($3$1 src1 (LShift$1 (And$1 src2 mask) lshift))); + ins_cost(1.9 * INSN_COST); + format %{ "$4 $dst, $src1, $src2, $5 #lshift" %} + + ins_encode %{ + __ $4(as_Register($dst$$reg), as_Register($src1$$reg), + as_Register($src2$$reg), ext::$5, ($lshift$$constant)); + %} + ins_pipe(ialu_reg_reg_shift); +%}') +dnl +dnl $1 $2 $3 $4 $5 +ADD_SUB_ZERO_EXTEND_SHIFT(L,255,Add,add,uxtb) +ADD_SUB_ZERO_EXTEND_SHIFT(L,65535,Add,add,uxth) +ADD_SUB_ZERO_EXTEND_SHIFT(L,4294967295,Add,add,uxtw) +dnl +ADD_SUB_ZERO_EXTEND_SHIFT(L,255,Sub,sub,uxtb) +ADD_SUB_ZERO_EXTEND_SHIFT(L,65535,Sub,sub,uxth) +ADD_SUB_ZERO_EXTEND_SHIFT(L,4294967295,Sub,sub,uxtw) +dnl +ADD_SUB_ZERO_EXTEND_SHIFT(I,255,Add,addw,uxtb) +ADD_SUB_ZERO_EXTEND_SHIFT(I,65535,Add,addw,uxth) +dnl +ADD_SUB_ZERO_EXTEND_SHIFT(I,255,Sub,subw,uxtb) +ADD_SUB_ZERO_EXTEND_SHIFT(I,65535,Sub,subw,uxth) +dnl // END This section of the file is automatically generated. Do not edit -------------- diff --git a/hotspot/src/cpu/aarch64/vm/abstractInterpreter_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/abstractInterpreter_aarch64.cpp index 49a266e5480..e73f1521e32 100644 --- a/hotspot/src/cpu/aarch64/vm/abstractInterpreter_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/abstractInterpreter_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -28,6 +28,7 @@ #include "oops/constMethod.hpp" #include "oops/method.hpp" #include "runtime/frame.inline.hpp" +#include "utilities/align.hpp" #include "utilities/debug.hpp" #include "utilities/macros.hpp" @@ -53,27 +54,6 @@ int AbstractInterpreter::BasicType_as_index(BasicType type) { return i; } -// These should never be compiled since the interpreter will prefer -// the compiled version to the intrinsic version. -bool AbstractInterpreter::can_be_compiled(methodHandle m) { - switch (method_kind(m)) { - case Interpreter::java_lang_math_sin : // fall thru - case Interpreter::java_lang_math_cos : // fall thru - case Interpreter::java_lang_math_tan : // fall thru - case Interpreter::java_lang_math_abs : // fall thru - case Interpreter::java_lang_math_log : // fall thru - case Interpreter::java_lang_math_log10 : // fall thru - case Interpreter::java_lang_math_sqrt : // fall thru - case Interpreter::java_lang_math_pow : // fall thru - case Interpreter::java_lang_math_exp : // fall thru - case Interpreter::java_lang_math_fmaD : // fall thru - case Interpreter::java_lang_math_fmaF : - return false; - default: - return true; - } -} - // How much stack a method activation needs in words. int AbstractInterpreter::size_top_interpreter_activation(Method* method) { const int entry_size = frame::interpreter_frame_monitor_size(); @@ -121,7 +101,7 @@ int AbstractInterpreter::size_activation(int max_stack, // On AArch64 we always keep the stack pointer 16-aligned, so we // must round up here. - size = round_to(size, 2); + size = align_up(size, 2); return size; } diff --git a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp index 2f97a3e11d3..6dc260f5a54 100644 --- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp @@ -2201,6 +2201,8 @@ public: INSN(fdiv, 1, 0, 0b111111); INSN(fmul, 1, 0, 0b110111); INSN(fsub, 0, 1, 0b110101); + INSN(fmla, 0, 0, 0b110011); + INSN(fmls, 0, 1, 0b110011); #undef INSN diff --git a/hotspot/src/cpu/aarch64/vm/bytes_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/bytes_aarch64.hpp index fc7890e945b..701d3af7fc0 100644 --- a/hotspot/src/cpu/aarch64/vm/bytes_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/bytes_aarch64.hpp @@ -30,12 +30,6 @@ class Bytes: AllStatic { public: - // Returns true if the byte ordering used by Java is different from the native byte ordering - // of the underlying machine. For example, this is true for Intel x86, but false for Solaris - // on Sparc. - static inline bool is_Java_byte_ordering_different(){ return true; } - - // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering // (no special code is needed since x86 CPUs can access unaligned data) static inline u2 get_native_u2(address p) { return *(u2*)p; } diff --git a/hotspot/src/cpu/aarch64/vm/c1_FpuStackSim_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_FpuStackSim_aarch64.cpp index 2db73cd1523..3e213003947 100644 --- a/hotspot/src/cpu/aarch64/vm/c1_FpuStackSim_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/c1_FpuStackSim_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -23,12 +23,6 @@ * */ -#include "precompiled.hpp" -#include "c1/c1_FpuStackSim.hpp" -#include "c1/c1_FrameMap.hpp" -#include "utilities/array.hpp" -#include "utilities/ostream.hpp" - //-------------------------------------------------------- // FpuStackSim //-------------------------------------------------------- diff --git a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp index 0016aa9ba6a..e6d9de99685 100644 --- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp @@ -2740,8 +2740,7 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { // set already but no need to check. __ cbz(rscratch1, next); - __ andr(rscratch1, tmp, TypeEntries::type_unknown); - __ cbnz(rscratch1, next); // already unknown. Nothing to do anymore. + __ tbnz(tmp, exact_log2(TypeEntries::type_unknown), next); // already unknown. Nothing to do anymore. if (TypeEntries::is_type_none(current_klass)) { __ cbz(rscratch2, none); @@ -2761,8 +2760,7 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "conflict only"); __ ldr(tmp, mdo_addr); - __ andr(rscratch1, tmp, TypeEntries::type_unknown); - __ cbnz(rscratch1, next); // already unknown. Nothing to do anymore. + __ tbnz(tmp, exact_log2(TypeEntries::type_unknown), next); // already unknown. Nothing to do anymore. } // different than before. Cannot keep accurate profile. @@ -2812,8 +2810,7 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { ciTypeEntries::valid_ciklass(current_klass) != exact_klass, "inconsistent"); __ ldr(tmp, mdo_addr); - __ andr(rscratch1, tmp, TypeEntries::type_unknown); - __ cbnz(rscratch1, next); // already unknown. Nothing to do anymore. + __ tbnz(tmp, exact_log2(TypeEntries::type_unknown), next); // already unknown. Nothing to do anymore. __ orr(tmp, tmp, TypeEntries::type_unknown); __ str(tmp, mdo_addr); diff --git a/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp index fe48df281b1..ab53d646d80 100644 --- a/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/frame_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -784,6 +784,8 @@ extern "C" void pm(unsigned long fp, unsigned long bcx) { frame::frame(void* sp, void* fp, void* pc) { init((intptr_t*)sp, (intptr_t*)fp, (address)pc); } + +void frame::pd_ps() {} #endif void JavaFrameAnchor::make_walkable(JavaThread* thread) { diff --git a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp index 06ec817cd9b..ba6e3eb637f 100644 --- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp @@ -154,8 +154,11 @@ define_pd_global(intx, InlineSmallCode, 1000); product(intx, BlockZeroingLowLimit, 256, \ "Minimum size in bytes when block zeroing will be used") \ range(1, max_jint) \ - product(bool, TraceTraps, false, "Trace all traps the signal handler") - + product(bool, TraceTraps, false, "Trace all traps the signal handler")\ + product(int, SoftwarePrefetchHintDistance, -1, \ + "Use prfm hint with specified distance in compiled code." \ + "Value -1 means off.") \ + range(-1, 32760) #endif diff --git a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp index 81636fb8ea1..480a6435f3d 100644 --- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -270,7 +270,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( get_constant_pool(result); // load pointer for resolved_references[] objArray - ldr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes())); + ldr(result, Address(result, ConstantPool::cache_offset_in_bytes())); + ldr(result, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes())); // JNIHandles::resolve(obj); ldr(result, Address(result, 0)); // Add in the index @@ -278,6 +279,15 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); } +void InterpreterMacroAssembler::load_resolved_klass_at_offset( + Register cpool, Register index, Register klass, Register temp) { + add(temp, cpool, index, LSL, LogBytesPerWord); + ldrh(temp, Address(temp, sizeof(ConstantPool))); // temp = resolved_klass_index + ldr(klass, Address(cpool, ConstantPool::resolved_klasses_offset_in_bytes())); // klass = cpool->_resolved_klasses + add(klass, klass, temp, LSL, LogBytesPerWord); + ldr(klass, Address(klass, Array::base_offset_in_bytes())); +} + // Generate a subtype check: branch to ok_is_subtype if sub_klass is a // subtype of super_klass. // @@ -682,7 +692,7 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) } // Load (object->mark() | 1) into swap_reg - ldr(rscratch1, Address(obj_reg, 0)); + ldr(rscratch1, Address(obj_reg, oopDesc::mark_offset_in_bytes())); orr(swap_reg, rscratch1, 1); // Save (object->mark() | 1) into BasicLock's displaced header @@ -694,14 +704,14 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) Label fail; if (PrintBiasedLockingStatistics) { Label fast; - cmpxchgptr(swap_reg, lock_reg, obj_reg, rscratch1, fast, &fail); + cmpxchg_obj_header(swap_reg, lock_reg, obj_reg, rscratch1, fast, &fail); bind(fast); atomic_incw(Address((address)BiasedLocking::fast_path_entry_count_addr()), rscratch2, rscratch1, tmp); b(done); bind(fail); } else { - cmpxchgptr(swap_reg, lock_reg, obj_reg, rscratch1, done, /*fallthrough*/NULL); + cmpxchg_obj_header(swap_reg, lock_reg, obj_reg, rscratch1, done, /*fallthrough*/NULL); } // Test if the oopMark is an obvious stack pointer, i.e., @@ -791,7 +801,7 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) cbz(header_reg, done); // Atomic swap back the old header - cmpxchgptr(swap_reg, header_reg, obj_reg, rscratch1, done, /*fallthrough*/NULL); + cmpxchg_obj_header(swap_reg, header_reg, obj_reg, rscratch1, done, /*fallthrough*/NULL); // Call the runtime routine for slow case. str(obj_reg, Address(lock_reg, BasicObjectLock::obj_offset_in_bytes())); // restore obj @@ -1744,8 +1754,7 @@ void InterpreterMacroAssembler::profile_parameters_type(Register mdp, Register t // Load the offset of the area within the MDO used for // parameters. If it's negative we're not profiling any parameters ldr(tmp1, Address(mdp, in_bytes(MethodData::parameters_type_data_di_offset()) - in_bytes(MethodData::data_offset()))); - cmp(tmp1, 0u); - br(Assembler::LT, profile_continue); + tbnz(tmp1, 63, profile_continue); // i.e. sign bit set // Compute a pointer to the area for parameters from the offset // and move the pointer to the slot for the last diff --git a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp index 925690b0d80..637ae481f5b 100644 --- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -54,9 +54,6 @@ class InterpreterMacroAssembler: public MacroAssembler { int number_of_arguments, bool check_exceptions); - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - // base routine for all dispatches void dispatch_base(TosState state, address* table, bool verifyoop = true); @@ -67,6 +64,9 @@ class InterpreterMacroAssembler: public MacroAssembler { void jump_to_entry(address entry); + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + // Interpreter-specific registers void save_bcp() { str(rbcp, Address(rfp, frame::interpreter_frame_bcp_offset * wordSize)); @@ -123,6 +123,9 @@ class InterpreterMacroAssembler: public MacroAssembler { // load cpool->resolved_references(index); void load_resolved_reference_at_index(Register result, Register index); + // load cpool->resolved_klass_at(index); + void load_resolved_klass_at_offset(Register cpool, Register index, Register klass, Register temp); + void pop_ptr(Register r = r0); void pop_i(Register r = r0); void pop_l(Register r = r0); diff --git a/hotspot/src/cpu/aarch64/vm/interpreterRT_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/interpreterRT_aarch64.cpp index 3914f4e4020..f174b67d146 100644 --- a/hotspot/src/cpu/aarch64/vm/interpreterRT_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/interpreterRT_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -369,7 +369,7 @@ class SlowSignatureHandler } public: - SlowSignatureHandler(methodHandle method, address from, intptr_t* to) + SlowSignatureHandler(const methodHandle& method, address from, intptr_t* to) : NativeSignatureIterator(method) { _from = from; diff --git a/hotspot/src/cpu/aarch64/vm/interpreterRT_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/interpreterRT_aarch64.hpp index 10c92c3b2ed..e0b1ecbba17 100644 --- a/hotspot/src/cpu/aarch64/vm/interpreterRT_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/interpreterRT_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -47,7 +47,7 @@ class SignatureHandlerGenerator: public NativeSignatureIterator { public: // Creation - SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) { + SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) { _masm = new MacroAssembler(buffer); _num_int_args = (method->is_static() ? 1 : 0); _num_fp_args = 0; diff --git a/hotspot/src/cpu/aarch64/vm/jniFastGetField_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/jniFastGetField_aarch64.cpp index a09c5230dc4..b0f9acee633 100644 --- a/hotspot/src/cpu/aarch64/vm/jniFastGetField_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/jniFastGetField_aarch64.cpp @@ -76,8 +76,7 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { SafepointSynchronize::safepoint_counter_addr(), offset); Address safepoint_counter_addr(rcounter_addr, offset); __ ldrw(rcounter, safepoint_counter_addr); - __ andw(rscratch1, rcounter, 1); - __ cbnzw(rscratch1, slow); + __ tbnz(rcounter, 0, slow); __ eor(robj, c_rarg1, rcounter); __ eor(robj, robj, rcounter); // obj, since // robj ^ rcounter ^ rcounter == robj diff --git a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp index f9cc50fe4d0..bebd5ae8ca9 100644 --- a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -55,7 +55,7 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) } } #endif // ASSERT - Handle obj = HotSpotObjectConstantImpl::object(constant); + Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant)); jobject value = JNIHandles::make_local(obj()); MacroAssembler::patch_oop(pc, (address)obj()); int oop_index = _oop_recorder->find_index(value); diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp index 303c2f5eb8e..d5deb80ed9a 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -38,6 +38,7 @@ #include "opto/compile.hpp" #include "opto/intrinsicnode.hpp" #include "opto/node.hpp" +#include "prims/jvm.h" #include "runtime/biasedLocking.hpp" #include "runtime/icache.hpp" #include "runtime/interfaceSupport.hpp" @@ -515,7 +516,7 @@ int MacroAssembler::biased_locking_enter(Register lock_reg, mov(rscratch1, markOopDesc::biased_lock_mask_in_place | markOopDesc::age_mask_in_place | markOopDesc::epoch_mask_in_place); andr(swap_reg, swap_reg, rscratch1); orr(tmp_reg, swap_reg, rthread); - cmpxchgptr(swap_reg, tmp_reg, obj_reg, rscratch1, here, slow_case); + cmpxchg_obj_header(swap_reg, tmp_reg, obj_reg, rscratch1, here, slow_case); // If the biasing toward our thread failed, this means that // another thread succeeded in biasing it toward itself and we // need to revoke that bias. The revocation will occur in the @@ -542,7 +543,7 @@ int MacroAssembler::biased_locking_enter(Register lock_reg, Label here; load_prototype_header(tmp_reg, obj_reg); orr(tmp_reg, rthread, tmp_reg); - cmpxchgptr(swap_reg, tmp_reg, obj_reg, rscratch1, here, slow_case); + cmpxchg_obj_header(swap_reg, tmp_reg, obj_reg, rscratch1, here, slow_case); // If the biasing toward our thread failed, then another thread // succeeded in biasing it toward itself and we need to revoke that // bias. The revocation will occur in the runtime in the slow case. @@ -569,7 +570,7 @@ int MacroAssembler::biased_locking_enter(Register lock_reg, { Label here, nope; load_prototype_header(tmp_reg, obj_reg); - cmpxchgptr(swap_reg, tmp_reg, obj_reg, rscratch1, here, &nope); + cmpxchg_obj_header(swap_reg, tmp_reg, obj_reg, rscratch1, here, &nope); bind(here); // Fall through to the normal CAS-based lock, because no matter what @@ -2011,6 +2012,12 @@ void MacroAssembler::stop(const char* msg) { hlt(0); } +void MacroAssembler::unimplemented(const char* what) { + char* b = new char[1024]; + jio_snprintf(b, 1024, "unimplemented: %s", what); + stop(b); +} + // If a constant does not fit in an immediate field, generate some // number of MOV instructions and then perform the operation. void MacroAssembler::wrap_add_sub_imm_insn(Register Rd, Register Rn, unsigned imm, @@ -2141,6 +2148,12 @@ void MacroAssembler::cmpxchgptr(Register oldv, Register newv, Register addr, Reg b(*fail); } +void MacroAssembler::cmpxchg_obj_header(Register oldv, Register newv, Register obj, Register tmp, + Label &succeed, Label *fail) { + assert(oopDesc::mark_offset_in_bytes() == 0, "assumption"); + cmpxchgptr(oldv, newv, obj, tmp, succeed, fail); +} + void MacroAssembler::cmpxchgw(Register oldv, Register newv, Register addr, Register tmp, Label &succeed, Label *fail) { // oldv holds comparison value @@ -4816,6 +4829,62 @@ void MacroAssembler::string_compare(Register str1, Register str2, BLOCK_COMMENT("} string_compare"); } +// This method checks if provided byte array contains byte with highest bit set. +void MacroAssembler::has_negatives(Register ary1, Register len, Register result) { + // Simple and most common case of aligned small array which is not at the + // end of memory page is placed here. All other cases are in stub. + Label LOOP, END, STUB, STUB_LONG, SET_RESULT, DONE; + const uint64_t UPPER_BIT_MASK=0x8080808080808080; + assert_different_registers(ary1, len, result); + + cmpw(len, 0); + br(LE, SET_RESULT); + cmpw(len, 4 * wordSize); + br(GE, STUB_LONG); // size > 32 then go to stub + + int shift = 64 - exact_log2(os::vm_page_size()); + lsl(rscratch1, ary1, shift); + mov(rscratch2, (size_t)(4 * wordSize) << shift); + adds(rscratch2, rscratch1, rscratch2); // At end of page? + br(CS, STUB); // at the end of page then go to stub + subs(len, len, wordSize); + br(LT, END); + + BIND(LOOP); + ldr(rscratch1, Address(post(ary1, wordSize))); + tst(rscratch1, UPPER_BIT_MASK); + br(NE, SET_RESULT); + subs(len, len, wordSize); + br(GE, LOOP); + cmpw(len, -wordSize); + br(EQ, SET_RESULT); + + BIND(END); + ldr(result, Address(ary1)); + sub(len, zr, len, LSL, 3); // LSL 3 is to get bits from bytes + lslv(result, result, len); + tst(result, UPPER_BIT_MASK); + b(SET_RESULT); + + BIND(STUB); + RuntimeAddress has_neg = RuntimeAddress(StubRoutines::aarch64::has_negatives()); + assert(has_neg.target() != NULL, "has_negatives stub has not been generated"); + trampoline_call(has_neg); + b(DONE); + + BIND(STUB_LONG); + RuntimeAddress has_neg_long = RuntimeAddress( + StubRoutines::aarch64::has_negatives_long()); + assert(has_neg_long.target() != NULL, "has_negatives stub has not been generated"); + trampoline_call(has_neg_long); + b(DONE); + + BIND(SET_RESULT); + cset(result, NE); // set true or false + + BIND(DONE); +} + // Compare Strings or char/byte arrays. // is_string is true iff this is a string comparison. diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp index 59171e5dd19..158e83c3cdb 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -77,12 +77,6 @@ class MacroAssembler: public Assembler { bool check_exceptions // whether to check for pending exceptions after return ); - // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. - // The implementation is only non-empty for the InterpreterMacroAssembler, - // as only the interpreter handles PopFrame and ForceEarlyReturn requests. - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true); // Maximum size of class area in Metaspace when compressed @@ -97,6 +91,12 @@ class MacroAssembler: public Assembler { > (1u << log2_intptr(CompressedClassSpaceSize)))); } + // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. + // The implementation is only non-empty for the InterpreterMacroAssembler, + // as only the interpreter handles PopFrame and ForceEarlyReturn requests. + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + // Biased locking support // lock_reg and obj_reg must be loaded up with the appropriate values. // swap_reg is killed. @@ -169,6 +169,7 @@ class MacroAssembler: public Assembler { template inline void cmpw(Register Rd, T imm) { subsw(zr, Rd, imm); } + // imm is limited to 12 bits. inline void cmp(Register Rd, unsigned imm) { subs(zr, Rd, imm); } inline void cmnw(Register Rd, unsigned imm) { addsw(zr, Rd, imm); } @@ -941,7 +942,7 @@ public: void untested() { stop("untested"); } - void unimplemented(const char* what = "") { char* b = new char[1024]; jio_snprintf(b, 1024, "unimplemented: %s", what); stop(b); } + void unimplemented(const char* what = ""); void should_not_reach_here() { stop("should not reach here"); } @@ -949,8 +950,8 @@ public: void bang_stack_with_offset(int offset) { // stack grows down, caller passes positive offset assert(offset > 0, "must bang with negative offset"); - mov(rscratch2, -offset); - str(zr, Address(sp, rscratch2)); + sub(rscratch2, sp, offset); + str(zr, Address(rscratch2)); } // Writes to stack successive pages until offset reached to check for @@ -974,6 +975,8 @@ public: // Various forms of CAS + void cmpxchg_obj_header(Register oldv, Register newv, Register obj, Register tmp, + Label &suceed, Label *fail); void cmpxchgptr(Register oldv, Register newv, Register addr, Register tmp, Label &suceed, Label *fail); @@ -1207,6 +1210,8 @@ public: Register tmp1, FloatRegister vtmp, FloatRegister vtmpZ, int ae); + void has_negatives(Register ary1, Register len, Register result); + void arrays_equals(Register a1, Register a2, Register result, Register cnt1, int elem_size, bool is_string); diff --git a/hotspot/src/cpu/aarch64/vm/metaspaceShared_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/metaspaceShared_aarch64.cpp deleted file mode 100644 index 72af9a84f04..00000000000 --- a/hotspot/src/cpu/aarch64/vm/metaspaceShared_aarch64.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, Red Hat Inc. 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 "asm/macroAssembler.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -extern "C" { - void aarch64_prolog(void); -} - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - -#ifdef BUILTIN_SIM - // Write a dummy word to the writable shared metaspace. - // MetaspaceShared::initialize_shared_spaces will fill it with the - // address of aarch64_prolog(). - address *prolog_ptr = (address*)*md_top; - *(intptr_t *)(*md_top) = (intptr_t)0; - (*md_top) += sizeof(intptr_t); -#endif - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - Label common_code; - for (int i = 0; i < vtbl_list_size; ++i) { - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*)masm->pc(); - - // We're called directly from C code. -#ifdef BUILTIN_SIM - __ c_stub_prolog(8, 0, MacroAssembler::ret_type_integral, prolog_ptr); -#endif - // Load rscratch1 with a value indicating vtable/offset pair. - // -- bits[ 7..0] (8 bits) which virtual method in table? - // -- bits[12..8] (5 bits) which virtual method table? - __ mov(rscratch1, (i << 8) + j); - __ b(common_code); - } - } - - __ bind(common_code); - - Register tmp0 = r10, tmp1 = r11; // AAPCS64 temporary registers - __ enter(); - __ lsr(tmp0, rscratch1, 8); // isolate vtable identifier. - __ mov(tmp1, (address)vtbl_list); // address of list of vtable pointers. - __ ldr(tmp1, Address(tmp1, tmp0, Address::lsl(LogBytesPerWord))); // get correct vtable pointer. - __ str(tmp1, Address(c_rarg0)); // update vtable pointer in obj. - __ add(rscratch1, tmp1, rscratch1, ext::uxtb, LogBytesPerWord); // address of real method pointer. - __ ldr(rscratch1, Address(rscratch1)); // get real method pointer. - __ blrt(rscratch1, 8, 0, 1); // jump to the real method. - __ leave(); - __ ret(lr); - - *mc_top = (char*)__ pc(); -} - -#ifdef BUILTIN_SIM -void MetaspaceShared::relocate_vtbl_list(char **buffer) { - void **sim_entry = (void**)*buffer; - *sim_entry = (void*)aarch64_prolog; - *buffer += sizeof(intptr_t); -} -#endif diff --git a/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp index dedabb6729b..cc837ee83af 100644 --- a/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/methodHandles_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -63,7 +63,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register obj, SystemDictionary::WKID klass_id, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); Register temp = rscratch2; Register temp2 = rscratch1; // used by MacroAssembler::cmpptr Label L_ok, L_bad; @@ -137,8 +137,9 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, __ verify_oop(method_temp); __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()))); __ verify_oop(method_temp); - // the following assumes that a Method* is normally compressed in the vmtarget field: - __ ldr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()))); + __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()))); + __ verify_oop(method_temp); + __ ldr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()))); if (VerifyMethodHandles && !for_compiler_entry) { // make sure recv is already on stack @@ -282,7 +283,8 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes())); Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes())); - Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())); + Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())); + Address vmtarget_method( rmethod, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())); Register temp1_recv_klass = temp1; if (iid != vmIntrinsics::_linkToStatic) { @@ -335,14 +337,16 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3); } - __ ldr(rmethod, member_vmtarget); + __ load_heap_oop(rmethod, member_vmtarget); + __ ldr(rmethod, vmtarget_method); break; case vmIntrinsics::_linkToStatic: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3); } - __ ldr(rmethod, member_vmtarget); + __ load_heap_oop(rmethod, member_vmtarget); + __ ldr(rmethod, vmtarget_method); break; case vmIntrinsics::_linkToVirtual: diff --git a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp index a286102e7b1..ac55da31ea9 100644 --- a/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/sharedRuntime_aarch64.cpp @@ -36,6 +36,7 @@ #include "oops/compiledICHolder.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/align.hpp" #include "vmreg_aarch64.inline.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" @@ -123,7 +124,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ assert(!save_vectors, "vectors are generated only by C2 and JVMCI"); #endif - int frame_size_in_bytes = round_to(additional_frame_words*wordSize + + int frame_size_in_bytes = align_up(additional_frame_words*wordSize + reg_save_size*BytesPerInt, 16); // OopMap frame size is in compiler stack slots (jint's) not bytes or words int frame_size_in_slots = frame_size_in_bytes / BytesPerInt; @@ -190,7 +191,7 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm) { __ ldr(r0, Address(sp, r0_offset_in_bytes())); // Pop all of the register save are off the stack - __ add(sp, sp, round_to(return_offset_in_bytes(), 16)); + __ add(sp, sp, align_up(return_offset_in_bytes(), 16)); } // Is vector's size (in bytes) bigger than a size saved by default? @@ -317,7 +318,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt, } } - return round_to(stk_args, 2); + return align_up(stk_args, 2); } // Patch the callers callsite with entry to compiled code if it exists. @@ -375,7 +376,7 @@ static void gen_c2i_adapter(MacroAssembler *masm, __ mov(r13, sp); // stack is aligned, keep it that way - extraspace = round_to(extraspace, 2*wordSize); + extraspace = align_up(extraspace, 2*wordSize); if (extraspace) __ sub(sp, sp, extraspace); @@ -547,7 +548,7 @@ void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm, } // Cut-out for having no stack args. - int comp_words_on_stack = round_to(comp_args_on_stack*VMRegImpl::stack_slot_size, wordSize)>>LogBytesPerWord; + int comp_words_on_stack = align_up(comp_args_on_stack*VMRegImpl::stack_slot_size, wordSize)>>LogBytesPerWord; if (comp_args_on_stack) { __ sub(rscratch1, sp, comp_words_on_stack * wordSize); __ andr(sp, rscratch1, -16); @@ -1206,7 +1207,7 @@ static void rt_call(MacroAssembler* masm, address dest, int gpargs, int fpargs, } static void verify_oop_args(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, const BasicType* sig_bt, const VMRegPair* regs) { Register temp_reg = r19; // not part of any compiled calling seq @@ -1228,7 +1229,7 @@ static void verify_oop_args(MacroAssembler* masm, } static void gen_special_dispatch(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, const BasicType* sig_bt, const VMRegPair* regs) { verify_oop_args(masm, method, sig_bt, regs); @@ -1486,7 +1487,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, total_save_slots = double_slots * 2 + single_slots; // align the save area if (double_slots != 0) { - stack_slots = round_to(stack_slots, 2); + stack_slots = align_up(stack_slots, 2); } } @@ -1543,7 +1544,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Now compute actual number of stack words we need rounding to make // stack properly aligned. - stack_slots = round_to(stack_slots, StackAlignmentInSlots); + stack_slots = align_up(stack_slots, StackAlignmentInSlots); int stack_size = stack_slots * VMRegImpl::stack_slot_size; @@ -1842,7 +1843,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, } // Load (object->mark() | 1) into swap_reg %r0 - __ ldr(rscratch1, Address(obj_reg, 0)); + __ ldr(rscratch1, Address(obj_reg, oopDesc::mark_offset_in_bytes())); __ orr(swap_reg, rscratch1, 1); // Save (object->mark() | 1) into BasicLock's displaced header @@ -1850,7 +1851,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // src -> dest iff dest == r0 else r0 <- dest { Label here; - __ cmpxchgptr(r0, lock_reg, obj_reg, rscratch1, lock_done, /*fallthrough*/NULL); + __ cmpxchg_obj_header(r0, lock_reg, obj_reg, rscratch1, lock_done, /*fallthrough*/NULL); } // Hmm should this move to the slow path code area??? @@ -2029,7 +2030,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Atomic swap old header if oop still contains the stack lock Label succeed; - __ cmpxchgptr(r0, old_hdr, obj_reg, rscratch1, succeed, &slow_path_unlock); + __ cmpxchg_obj_header(r0, old_hdr, obj_reg, rscratch1, succeed, &slow_path_unlock); __ bind(succeed); // slow path re-enters here @@ -2293,7 +2294,7 @@ int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals) return 0; // No adjustment for negative locals int diff = (callee_locals - callee_parameters) * Interpreter::stackElementWords; // diff is counted in stack words - return round_to(diff, 2); + return align_up(diff, 2); } diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp index 650c374371d..e6e79a468d2 100644 --- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp @@ -39,6 +39,7 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" +#include "utilities/align.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif @@ -619,19 +620,21 @@ class StubGenerator: public StubCodeGenerator { // Generate code for an array write pre barrier // - // addr - starting address - // count - element count - // tmp - scratch register + // addr - starting address + // count - element count + // tmp - scratch register + // saved_regs - registers to be saved before calling static_write_ref_array_pre // - // Destroy no registers except rscratch1 and rscratch2 + // Callers must specify which registers to preserve in saved_regs. + // Clobbers: r0-r18, v0-v7, v16-v31, except saved_regs. // - void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) { + void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized, RegSet saved_regs) { BarrierSet* bs = Universe::heap()->barrier_set(); switch (bs->kind()) { case BarrierSet::G1SATBCTLogging: // With G1, don't generate the call if we statically know that the target in uninitialized if (!dest_uninitialized) { - __ push_call_clobbered_registers(); + __ push(saved_regs, sp); if (count == c_rarg0) { if (addr == c_rarg1) { // exactly backwards!! @@ -647,7 +650,7 @@ class StubGenerator: public StubCodeGenerator { __ mov(c_rarg1, count); } __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2); - __ pop_call_clobbered_registers(); + __ pop(saved_regs, sp); break; case BarrierSet::CardTableForRS: case BarrierSet::CardTableExtension: @@ -664,20 +667,23 @@ class StubGenerator: public StubCodeGenerator { // Generate code for an array write post barrier // // Input: - // start - register containing starting address of destination array - // end - register containing ending address of destination array - // scratch - scratch register + // start - register containing starting address of destination array + // end - register containing ending address of destination array + // scratch - scratch register + // saved_regs - registers to be saved before calling static_write_ref_array_post // // The input registers are overwritten. // The ending address is inclusive. - void gen_write_ref_array_post_barrier(Register start, Register end, Register scratch) { + // Callers must specify which registers to preserve in saved_regs. + // Clobbers: r0-r18, v0-v7, v16-v31, except saved_regs. + void gen_write_ref_array_post_barrier(Register start, Register end, Register scratch, RegSet saved_regs) { assert_different_registers(start, end, scratch); BarrierSet* bs = Universe::heap()->barrier_set(); switch (bs->kind()) { case BarrierSet::G1SATBCTLogging: { - __ push_call_clobbered_registers(); + __ push(saved_regs, sp); // must compute element count unless barrier set interface is changed (other platforms supply count) assert_different_registers(start, end, scratch); __ lea(scratch, Address(end, BytesPerHeapOop)); @@ -686,7 +692,7 @@ class StubGenerator: public StubCodeGenerator { __ mov(c_rarg0, start); __ mov(c_rarg1, scratch); __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), 2); - __ pop_call_clobbered_registers(); + __ pop(saved_regs, sp); } break; case BarrierSet::CardTableForRS: @@ -758,7 +764,7 @@ class StubGenerator: public StubCodeGenerator { // alignment. Label small; int low_limit = MAX2(zva_length * 2, (int)BlockZeroingLowLimit); - __ cmp(cnt, low_limit >> 3); + __ subs(rscratch1, cnt, low_limit >> 3); __ br(Assembler::LT, small); __ zero_dcache_blocks(base, cnt); __ bind(small); @@ -821,7 +827,7 @@ class StubGenerator: public StubCodeGenerator { Label again, drain; const char *stub_name; if (direction == copy_forwards) - stub_name = "foward_copy_longs"; + stub_name = "forward_copy_longs"; else stub_name = "backward_copy_longs"; StubCodeMark mark(this, "StubRoutines", stub_name); @@ -1438,6 +1444,7 @@ class StubGenerator: public StubCodeGenerator { address generate_disjoint_copy(size_t size, bool aligned, bool is_oop, address *entry, const char *name, bool dest_uninitialized = false) { Register s = c_rarg0, d = c_rarg1, count = c_rarg2; + RegSet saved_reg = RegSet::of(s, d, count); __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); @@ -1450,9 +1457,9 @@ class StubGenerator: public StubCodeGenerator { } if (is_oop) { + gen_write_ref_array_pre_barrier(d, count, dest_uninitialized, saved_reg); + // save regs before copy_memory __ push(RegSet::of(d, count), sp); - // no registers are destroyed by this call - gen_write_ref_array_pre_barrier(d, count, dest_uninitialized); } copy_memory(aligned, s, d, count, rscratch1, size); if (is_oop) { @@ -1461,7 +1468,7 @@ class StubGenerator: public StubCodeGenerator { verify_oop_array(size, d, count, r16); __ sub(count, count, 1); // make an inclusive end pointer __ lea(count, Address(d, count, Address::lsl(exact_log2(size)))); - gen_write_ref_array_post_barrier(d, count, rscratch1); + gen_write_ref_array_post_barrier(d, count, rscratch1, RegSet()); } __ leave(); __ mov(r0, zr); // return 0 @@ -1494,7 +1501,7 @@ class StubGenerator: public StubCodeGenerator { address *entry, const char *name, bool dest_uninitialized = false) { Register s = c_rarg0, d = c_rarg1, count = c_rarg2; - + RegSet saved_regs = RegSet::of(s, d, count); StubCodeMark mark(this, "StubRoutines", name); address start = __ pc(); __ enter(); @@ -1511,9 +1518,9 @@ class StubGenerator: public StubCodeGenerator { __ br(Assembler::HS, nooverlap_target); if (is_oop) { + gen_write_ref_array_pre_barrier(d, count, dest_uninitialized, saved_regs); + // save regs before copy_memory __ push(RegSet::of(d, count), sp); - // no registers are destroyed by this call - gen_write_ref_array_pre_barrier(d, count, dest_uninitialized); } copy_memory(aligned, s, d, count, rscratch1, -size); if (is_oop) { @@ -1522,7 +1529,7 @@ class StubGenerator: public StubCodeGenerator { verify_oop_array(size, d, count, r16); __ sub(count, count, 1); // make an inclusive end pointer __ lea(count, Address(d, count, Address::lsl(exact_log2(size)))); - gen_write_ref_array_post_barrier(d, count, rscratch1); + gen_write_ref_array_post_barrier(d, count, rscratch1, RegSet()); } __ leave(); __ mov(r0, zr); // return 0 @@ -1804,6 +1811,9 @@ class StubGenerator: public StubCodeGenerator { const Register ckoff = c_rarg3; // super_check_offset const Register ckval = c_rarg4; // super_klass + RegSet wb_pre_saved_regs = RegSet::range(c_rarg0, c_rarg4); + RegSet wb_post_saved_regs = RegSet::of(count); + // Registers used as temps (r18, r19, r20 are save-on-entry) const Register count_save = r21; // orig elementscount const Register start_to = r20; // destination array start address @@ -1861,7 +1871,7 @@ class StubGenerator: public StubCodeGenerator { } #endif //ASSERT - gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); + gen_write_ref_array_pre_barrier(to, count, dest_uninitialized, wb_pre_saved_regs); // save the original count __ mov(count_save, count); @@ -1905,7 +1915,7 @@ class StubGenerator: public StubCodeGenerator { __ BIND(L_do_card_marks); __ add(to, to, -heapOopSize); // make an inclusive end pointer - gen_write_ref_array_post_barrier(start_to, to, rscratch1); + gen_write_ref_array_post_barrier(start_to, to, rscratch1, wb_post_saved_regs); __ bind(L_done_pop); __ pop(RegSet::of(r18, r19, r20, r21), sp); @@ -3660,6 +3670,167 @@ class StubGenerator: public StubCodeGenerator { __ eor(result, __ T16B, lo, t0); } + address generate_has_negatives(address &has_negatives_long) { + StubCodeMark mark(this, "StubRoutines", "has_negatives"); + const int large_loop_size = 64; + const uint64_t UPPER_BIT_MASK=0x8080808080808080; + int dcache_line = VM_Version::dcache_line_size(); + + Register ary1 = r1, len = r2, result = r0; + + __ align(CodeEntryAlignment); + address entry = __ pc(); + + __ enter(); + + Label RET_TRUE, RET_TRUE_NO_POP, RET_FALSE, ALIGNED, LOOP16, CHECK_16, DONE, + LARGE_LOOP, POST_LOOP16, LEN_OVER_15, LEN_OVER_8, POST_LOOP16_LOAD_TAIL; + + __ cmp(len, 15); + __ br(Assembler::GT, LEN_OVER_15); + // The only case when execution falls into this code is when pointer is near + // the end of memory page and we have to avoid reading next page + __ add(ary1, ary1, len); + __ subs(len, len, 8); + __ br(Assembler::GT, LEN_OVER_8); + __ ldr(rscratch2, Address(ary1, -8)); + __ sub(rscratch1, zr, len, __ LSL, 3); // LSL 3 is to get bits from bytes. + __ lsrv(rscratch2, rscratch2, rscratch1); + __ tst(rscratch2, UPPER_BIT_MASK); + __ cset(result, Assembler::NE); + __ leave(); + __ ret(lr); + __ bind(LEN_OVER_8); + __ ldp(rscratch1, rscratch2, Address(ary1, -16)); + __ sub(len, len, 8); // no data dep., then sub can be executed while loading + __ tst(rscratch2, UPPER_BIT_MASK); + __ br(Assembler::NE, RET_TRUE_NO_POP); + __ sub(rscratch2, zr, len, __ LSL, 3); // LSL 3 is to get bits from bytes + __ lsrv(rscratch1, rscratch1, rscratch2); + __ tst(rscratch1, UPPER_BIT_MASK); + __ cset(result, Assembler::NE); + __ leave(); + __ ret(lr); + + Register tmp1 = r3, tmp2 = r4, tmp3 = r5, tmp4 = r6, tmp5 = r7, tmp6 = r10; + const RegSet spilled_regs = RegSet::range(tmp1, tmp5) + tmp6; + + has_negatives_long = __ pc(); // 2nd entry point + + __ enter(); + + __ bind(LEN_OVER_15); + __ push(spilled_regs, sp); + __ andr(rscratch2, ary1, 15); // check pointer for 16-byte alignment + __ cbz(rscratch2, ALIGNED); + __ ldp(tmp6, tmp1, Address(ary1)); + __ mov(tmp5, 16); + __ sub(rscratch1, tmp5, rscratch2); // amount of bytes until aligned address + __ add(ary1, ary1, rscratch1); + __ sub(len, len, rscratch1); + __ orr(tmp6, tmp6, tmp1); + __ tst(tmp6, UPPER_BIT_MASK); + __ br(Assembler::NE, RET_TRUE); + + __ bind(ALIGNED); + __ cmp(len, large_loop_size); + __ br(Assembler::LT, CHECK_16); + // Perform 16-byte load as early return in pre-loop to handle situation + // when initially aligned large array has negative values at starting bytes, + // so LARGE_LOOP would do 4 reads instead of 1 (in worst case), which is + // slower. Cases with negative bytes further ahead won't be affected that + // much. In fact, it'll be faster due to early loads, less instructions and + // less branches in LARGE_LOOP. + __ ldp(tmp6, tmp1, Address(__ post(ary1, 16))); + __ sub(len, len, 16); + __ orr(tmp6, tmp6, tmp1); + __ tst(tmp6, UPPER_BIT_MASK); + __ br(Assembler::NE, RET_TRUE); + __ cmp(len, large_loop_size); + __ br(Assembler::LT, CHECK_16); + + if (SoftwarePrefetchHintDistance >= 0 + && SoftwarePrefetchHintDistance >= dcache_line) { + // initial prefetch + __ prfm(Address(ary1, SoftwarePrefetchHintDistance - dcache_line)); + } + __ bind(LARGE_LOOP); + if (SoftwarePrefetchHintDistance >= 0) { + __ prfm(Address(ary1, SoftwarePrefetchHintDistance)); + } + // Issue load instructions first, since it can save few CPU/MEM cycles, also + // instead of 4 triples of "orr(...), addr(...);cbnz(...);" (for each ldp) + // better generate 7 * orr(...) + 1 andr(...) + 1 cbnz(...) which saves 3 + // instructions per cycle and have less branches, but this approach disables + // early return, thus, all 64 bytes are loaded and checked every time. + __ ldp(tmp2, tmp3, Address(ary1)); + __ ldp(tmp4, tmp5, Address(ary1, 16)); + __ ldp(rscratch1, rscratch2, Address(ary1, 32)); + __ ldp(tmp6, tmp1, Address(ary1, 48)); + __ add(ary1, ary1, large_loop_size); + __ sub(len, len, large_loop_size); + __ orr(tmp2, tmp2, tmp3); + __ orr(tmp4, tmp4, tmp5); + __ orr(rscratch1, rscratch1, rscratch2); + __ orr(tmp6, tmp6, tmp1); + __ orr(tmp2, tmp2, tmp4); + __ orr(rscratch1, rscratch1, tmp6); + __ orr(tmp2, tmp2, rscratch1); + __ tst(tmp2, UPPER_BIT_MASK); + __ br(Assembler::NE, RET_TRUE); + __ cmp(len, large_loop_size); + __ br(Assembler::GE, LARGE_LOOP); + + __ bind(CHECK_16); // small 16-byte load pre-loop + __ cmp(len, 16); + __ br(Assembler::LT, POST_LOOP16); + + __ bind(LOOP16); // small 16-byte load loop + __ ldp(tmp2, tmp3, Address(__ post(ary1, 16))); + __ sub(len, len, 16); + __ orr(tmp2, tmp2, tmp3); + __ tst(tmp2, UPPER_BIT_MASK); + __ br(Assembler::NE, RET_TRUE); + __ cmp(len, 16); + __ br(Assembler::GE, LOOP16); // 16-byte load loop end + + __ bind(POST_LOOP16); // 16-byte aligned, so we can read unconditionally + __ cmp(len, 8); + __ br(Assembler::LE, POST_LOOP16_LOAD_TAIL); + __ ldr(tmp3, Address(__ post(ary1, 8))); + __ sub(len, len, 8); + __ tst(tmp3, UPPER_BIT_MASK); + __ br(Assembler::NE, RET_TRUE); + + __ bind(POST_LOOP16_LOAD_TAIL); + __ cbz(len, RET_FALSE); // Can't shift left by 64 when len==0 + __ ldr(tmp1, Address(ary1)); + __ mov(tmp2, 64); + __ sub(tmp4, tmp2, len, __ LSL, 3); + __ lslv(tmp1, tmp1, tmp4); + __ tst(tmp1, UPPER_BIT_MASK); + __ br(Assembler::NE, RET_TRUE); + // Fallthrough + + __ bind(RET_FALSE); + __ pop(spilled_regs, sp); + __ leave(); + __ mov(result, zr); + __ ret(lr); + + __ bind(RET_TRUE); + __ pop(spilled_regs, sp); + __ bind(RET_TRUE_NO_POP); + __ leave(); + __ mov(result, 1); + __ ret(lr); + + __ bind(DONE); + __ pop(spilled_regs, sp); + __ leave(); + __ ret(lr); + return entry; + } /** * Arguments: * @@ -4676,6 +4847,7 @@ class StubGenerator: public StubCodeGenerator { // } }; + // Initialization void generate_initial() { // Generate initial stubs and initializes the entry points @@ -4734,6 +4906,9 @@ class StubGenerator: public StubCodeGenerator { // arraycopy stubs used by compilers generate_arraycopy_stubs(); + // has negatives stub for large arrays. + StubRoutines::aarch64::_has_negatives = generate_has_negatives(StubRoutines::aarch64::_has_negatives_long); + if (UseMultiplyToLenIntrinsic) { StubRoutines::_multiplyToLen = generate_multiplyToLen(); } diff --git a/hotspot/src/cpu/aarch64/vm/stubRoutines_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubRoutines_aarch64.cpp index 9bcbe1e1e1d..1313166ca3a 100644 --- a/hotspot/src/cpu/aarch64/vm/stubRoutines_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/stubRoutines_aarch64.cpp @@ -44,6 +44,8 @@ address StubRoutines::aarch64::_float_sign_flip = NULL; address StubRoutines::aarch64::_double_sign_mask = NULL; address StubRoutines::aarch64::_double_sign_flip = NULL; address StubRoutines::aarch64::_zero_blocks = NULL; +address StubRoutines::aarch64::_has_negatives = NULL; +address StubRoutines::aarch64::_has_negatives_long = NULL; bool StubRoutines::aarch64::_completed = false; /** diff --git a/hotspot/src/cpu/aarch64/vm/stubRoutines_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/stubRoutines_aarch64.hpp index fc86d04a648..e7a6bc3c850 100644 --- a/hotspot/src/cpu/aarch64/vm/stubRoutines_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/stubRoutines_aarch64.hpp @@ -62,6 +62,9 @@ class aarch64 { static address _double_sign_flip; static address _zero_blocks; + + static address _has_negatives; + static address _has_negatives_long; static bool _completed; public: @@ -120,6 +123,14 @@ class aarch64 { return _zero_blocks; } + static address has_negatives() { + return _has_negatives; + } + + static address has_negatives_long() { + return _has_negatives_long; + } + static bool complete() { return _completed; } diff --git a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp index 6f44292c55a..f22f8d874aa 100644 --- a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp @@ -402,14 +402,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common( return entry; } -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - address entry = __ pc(); - // NULL last_sp until next java call - __ str(zr, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize)); - __ dispatch_next(state); - return entry; -} - address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address entry = __ pc(); @@ -444,6 +436,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ notify(Assembler::method_reentry); } #endif + + __ check_and_handle_popframe(rthread); + __ check_and_handle_earlyret(rthread); + __ get_dispatch(); __ dispatch_next(state, step); diff --git a/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp index f0f0f5a6ee5..e110035d31a 100644 --- a/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/templateTable_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -246,8 +246,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, assert(load_bc_into_bc_reg, "we use bc_reg as temp"); __ get_cache_and_index_and_bytecode_at_bcp(temp_reg, bc_reg, temp_reg, byte_no, 1); __ movw(bc_reg, bc); - __ cmpw(temp_reg, (unsigned) 0); - __ br(Assembler::EQ, L_patch_done); // don't patch + __ cbzw(temp_reg, L_patch_done); // don't patch } break; default: @@ -3418,8 +3417,7 @@ void TemplateTable::_new() { __ br(Assembler::NE, slow_case); // get InstanceKlass - __ lea(r4, Address(r4, r3, Address::lsl(3))); - __ ldr(r4, Address(r4, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(r4, r3, r4, rscratch1); // make sure klass is initialized & doesn't have finalizer // make sure klass is fully initialized @@ -3572,8 +3570,7 @@ void TemplateTable::checkcast() // Get superklass in r0 and subklass in r3 __ bind(quicked); __ mov(r3, r0); // Save object in r3; r0 needed for subtype check - __ lea(r0, Address(r2, r19, Address::lsl(3))); - __ ldr(r0, Address(r0, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(r2, r19, r0, rscratch1); // r0 = klass __ bind(resolved); __ load_klass(r19, r3); @@ -3629,8 +3626,7 @@ void TemplateTable::instanceof() { // Get superklass in r0 and subklass in r3 __ bind(quicked); __ load_klass(r3, r0); - __ lea(r0, Address(r2, r19, Address::lsl(3))); - __ ldr(r0, Address(r0, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(r2, r19, r0, rscratch1); __ bind(resolved); diff --git a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp index 33cb9496a91..722ebbba322 100644 --- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp @@ -137,6 +137,8 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(PrefetchScanIntervalInBytes, 3*dcache_line); if (FLAG_IS_DEFAULT(PrefetchCopyIntervalInBytes)) FLAG_SET_DEFAULT(PrefetchCopyIntervalInBytes, 3*dcache_line); + if (FLAG_IS_DEFAULT(SoftwarePrefetchHintDistance)) + FLAG_SET_DEFAULT(SoftwarePrefetchHintDistance, 3*dcache_line); if (PrefetchCopyIntervalInBytes != -1 && ((PrefetchCopyIntervalInBytes & 7) || (PrefetchCopyIntervalInBytes >= 32768))) { @@ -146,6 +148,12 @@ void VM_Version::get_processor_features() { PrefetchCopyIntervalInBytes = 32760; } + if (SoftwarePrefetchHintDistance != -1 && + (SoftwarePrefetchHintDistance & 7)) { + warning("SoftwarePrefetchHintDistance must be -1, or a multiple of 8"); + SoftwarePrefetchHintDistance &= ~7; + } + unsigned long auxv = getauxval(AT_HWCAP); char buf[512]; diff --git a/hotspot/src/cpu/arm/vm/abstractInterpreter_arm.cpp b/hotspot/src/cpu/arm/vm/abstractInterpreter_arm.cpp index 7899c102e5b..efc233a562e 100644 --- a/hotspot/src/cpu/arm/vm/abstractInterpreter_arm.cpp +++ b/hotspot/src/cpu/arm/vm/abstractInterpreter_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -32,6 +32,7 @@ #include "runtime/handles.inline.hpp" #include "runtime/frame.inline.hpp" #include "runtime/synchronizer.hpp" +#include "utilities/align.hpp" #include "utilities/macros.hpp" int AbstractInterpreter::BasicType_as_index(BasicType type) { @@ -68,23 +69,6 @@ int AbstractInterpreter::BasicType_as_index(BasicType type) { return i; } -// These should never be compiled since the interpreter will prefer -// the compiled version to the intrinsic version. -bool AbstractInterpreter::can_be_compiled(methodHandle m) { - switch (method_kind(m)) { - case Interpreter::java_lang_math_sin : // fall thru - case Interpreter::java_lang_math_cos : // fall thru - case Interpreter::java_lang_math_tan : // fall thru - case Interpreter::java_lang_math_abs : // fall thru - case Interpreter::java_lang_math_log : // fall thru - case Interpreter::java_lang_math_log10 : // fall thru - case Interpreter::java_lang_math_sqrt : - return false; - default: - return true; - } -} - // How much stack a method activation needs in words. int AbstractInterpreter::size_top_interpreter_activation(Method* method) { const int stub_code = AARCH64_ONLY(24) NOT_AARCH64(12); // see generate_call_stub @@ -125,7 +109,7 @@ int AbstractInterpreter::size_activation(int max_stack, tempcount*Interpreter::stackElementWords + extra_args; #ifdef AARCH64 - size = round_to(size, StackAlignmentInBytes/BytesPerWord); + size = align_up(size, StackAlignmentInBytes/BytesPerWord); #endif // AARCH64 return size; @@ -206,7 +190,7 @@ void AbstractInterpreter::layout_activation(Method* method, } if (caller->is_interpreted_frame()) { intptr_t* locals_base = (locals - method->max_locals()*Interpreter::stackElementWords + 1); - locals_base = (intptr_t*)round_down((intptr_t)locals_base, StackAlignmentInBytes); + locals_base = align_down(locals_base, StackAlignmentInBytes); assert(interpreter_frame->sender_sp() <= locals_base, "interpreter-to-interpreter frame chaining"); } else if (caller->is_compiled_frame()) { @@ -234,10 +218,17 @@ void AbstractInterpreter::layout_activation(Method* method, #ifdef AARCH64 interpreter_frame->interpreter_frame_set_stack_top(stack_top); + // We have to add extra reserved slots to max_stack. There are 3 users of the extra slots, + // none of which are at the same time, so we just need to make sure there is enough room + // for the biggest user: + // -reserved slot for exception handler + // -reserved slots for JSR292. Method::extra_stack_entries() is the size. + // -3 reserved slots so get_method_counters() can save some registers before call_VM(). + int max_stack = method->constMethod()->max_stack() + MAX2(3, Method::extra_stack_entries()); intptr_t* extended_sp = (intptr_t*) monbot - - (method->max_stack() + 1) * Interpreter::stackElementWords - // +1 is reserved slot for exception handler + (max_stack * Interpreter::stackElementWords) - popframe_extra_args; - extended_sp = (intptr_t*)round_down((intptr_t)extended_sp, StackAlignmentInBytes); + extended_sp = align_down(extended_sp, StackAlignmentInBytes); interpreter_frame->interpreter_frame_set_extended_sp(extended_sp); #else interpreter_frame->interpreter_frame_set_last_sp(stack_top); @@ -249,7 +240,7 @@ void AbstractInterpreter::layout_activation(Method* method, #ifdef AARCH64 if (caller->is_interpreted_frame()) { - intptr_t* sender_sp = (intptr_t*)round_down((intptr_t)caller->interpreter_frame_tos_address(), StackAlignmentInBytes); + intptr_t* sender_sp = align_down(caller->interpreter_frame_tos_address(), StackAlignmentInBytes); interpreter_frame->set_interpreter_frame_sender_sp(sender_sp); } else { diff --git a/hotspot/src/cpu/arm/vm/arm.ad b/hotspot/src/cpu/arm/vm/arm.ad index f4e5bd324cd..7cc789f599d 100644 --- a/hotspot/src/cpu/arm/vm/arm.ad +++ b/hotspot/src/cpu/arm/vm/arm.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2008, 2017, 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 @@ -1122,7 +1122,7 @@ const int Matcher::vector_width_in_bytes(BasicType bt) { } // Vector ideal reg corresponding to specified size in bytes -const int Matcher::vector_ideal_reg(int size) { +const uint Matcher::vector_ideal_reg(int size) { assert(MaxVectorSize >= size, ""); switch(size) { case 8: return Op_VecD; @@ -1132,7 +1132,7 @@ const int Matcher::vector_ideal_reg(int size) { return 0; } -const int Matcher::vector_shift_count_ideal_reg(int size) { +const uint Matcher::vector_shift_count_ideal_reg(int size) { return vector_ideal_reg(size); } @@ -1881,7 +1881,7 @@ frame %{ // Ret Addr is on stack in slot 0 if no locks or verification or alignment. // Otherwise, it is above the locks and verification slot and alignment word return_addr(STACK - 1*VMRegImpl::slots_per_word + - round_to((Compile::current()->in_preserve_stack_slots() + + align_up((Compile::current()->in_preserve_stack_slots() + Compile::current()->fixed_slots()), stack_alignment_in_slots())); @@ -11968,9 +11968,13 @@ instruct ShouldNotReachHere( ) size(4); // Use the following format syntax - format %{ "breakpoint ; ShouldNotReachHere" %} + format %{ "ShouldNotReachHere" %} ins_encode %{ - __ breakpoint(); +#ifdef AARCH64 + __ dpcs1(0xdead); +#else + __ udf(0xdead); +#endif %} ins_pipe(tail_call); %} diff --git a/hotspot/src/cpu/arm/vm/assembler_arm_32.hpp b/hotspot/src/cpu/arm/vm/assembler_arm_32.hpp index e32f6a98f29..95e6568832e 100644 --- a/hotspot/src/cpu/arm/vm/assembler_arm_32.hpp +++ b/hotspot/src/cpu/arm/vm/assembler_arm_32.hpp @@ -578,6 +578,11 @@ class Assembler : public AbstractAssembler { F(bl, 0xb) #undef F + void udf(int imm_16) { + assert((imm_16 >> 16) == 0, "encoding constraint"); + emit_int32(0xe7f000f0 | (imm_16 & 0xfff0) << 8 | (imm_16 & 0xf)); + } + // ARMv7 instructions #define F(mnemonic, wt) \ diff --git a/hotspot/src/cpu/arm/vm/assembler_arm_64.hpp b/hotspot/src/cpu/arm/vm/assembler_arm_64.hpp index 44d0504036c..9c6cd14c3f8 100644 --- a/hotspot/src/cpu/arm/vm/assembler_arm_64.hpp +++ b/hotspot/src/cpu/arm/vm/assembler_arm_64.hpp @@ -1083,6 +1083,7 @@ class Assembler : public AbstractAssembler { F(brk, 0b001, 0b000, 0b00) F(hlt, 0b010, 0b000, 0b00) + F(dpcs1, 0b101, 0b000, 0b01) #undef F enum SystemRegister { // o0<1> op1<3> CRn<4> CRm<4> op2<3> diff --git a/hotspot/src/cpu/arm/vm/bytes_arm.hpp b/hotspot/src/cpu/arm/vm/bytes_arm.hpp index 0cf7e2a77c9..0e5a894050a 100644 --- a/hotspot/src/cpu/arm/vm/bytes_arm.hpp +++ b/hotspot/src/cpu/arm/vm/bytes_arm.hpp @@ -35,12 +35,6 @@ class Bytes: AllStatic { public: - // Returns true if the byte ordering used by Java is different from the native byte ordering - // of the underlying machine. - static inline bool is_Java_byte_ordering_different() { - return VM_LITTLE_ENDIAN != 0; - } - static inline u2 get_Java_u2(address p) { return (u2(p[0]) << 8) | u2(p[1]); } diff --git a/hotspot/src/cpu/arm/vm/c1_FpuStackSim_arm.cpp b/hotspot/src/cpu/arm/vm/c1_FpuStackSim_arm.cpp index ac826b491a2..287f4e412d7 100644 --- a/hotspot/src/cpu/arm/vm/c1_FpuStackSim_arm.cpp +++ b/hotspot/src/cpu/arm/vm/c1_FpuStackSim_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -22,10 +22,4 @@ * */ -#include "precompiled.hpp" -#include "c1/c1_FpuStackSim.hpp" -#include "c1/c1_FrameMap.hpp" -#include "utilities/array.hpp" -#include "utilities/ostream.hpp" - // Nothing needed here diff --git a/hotspot/src/cpu/arm/vm/c1_Runtime1_arm.cpp b/hotspot/src/cpu/arm/vm/c1_Runtime1_arm.cpp index 5e793e16bd7..a4a969c87fa 100644 --- a/hotspot/src/cpu/arm/vm/c1_Runtime1_arm.cpp +++ b/hotspot/src/cpu/arm/vm/c1_Runtime1_arm.cpp @@ -37,6 +37,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/align.hpp" #include "vmreg_arm.inline.hpp" #if INCLUDE_ALL_GCS #include "gc/g1/g1SATBCardTableModRefBS.hpp" @@ -250,7 +251,7 @@ static OopMap* save_live_registers(StubAssembler* sasm, bool save_fpu_registers __ sub(SP, SP, (reg_save_size - 2) * wordSize); - for (int i = 0; i < round_down(number_of_saved_gprs, 2); i += 2) { + for (int i = 0; i < align_down((int)number_of_saved_gprs, 2); i += 2) { __ stp(as_Register(i), as_Register(i+1), Address(SP, (R0_offset + i) * wordSize)); } diff --git a/hotspot/src/cpu/arm/vm/frame_arm.cpp b/hotspot/src/cpu/arm/vm/frame_arm.cpp index defe4a45a4a..ae40ec808ff 100644 --- a/hotspot/src/cpu/arm/vm/frame_arm.cpp +++ b/hotspot/src/cpu/arm/vm/frame_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -621,6 +621,8 @@ void frame::describe_pd(FrameValues& values, int frame_no) { frame::frame(void* sp, void* fp, void* pc) { init((intptr_t*)sp, (intptr_t*)fp, (address)pc); } + +void frame::pd_ps() {} #endif intptr_t *frame::initial_deoptimization_info() { diff --git a/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp b/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp index 96df37c275e..364ce6e854c 100644 --- a/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp +++ b/hotspot/src/cpu/arm/vm/interp_masm_arm.cpp @@ -298,7 +298,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( Register cache = result; // load pointer for resolved_references[] objArray - ldr(cache, Address(result, ConstantPool::resolved_references_offset_in_bytes())); + ldr(cache, Address(result, ConstantPool::cache_offset_in_bytes())); + ldr(cache, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes())); // JNIHandles::resolve(result) ldr(cache, Address(cache, 0)); // Add in the index @@ -308,6 +309,15 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( load_heap_oop(result, Address(cache, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); } +void InterpreterMacroAssembler::load_resolved_klass_at_offset( + Register Rcpool, Register Rindex, Register Rklass) { + add(Rtemp, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord)); + ldrh(Rtemp, Address(Rtemp, sizeof(ConstantPool))); // Rtemp = resolved_klass_index + ldr(Rklass, Address(Rcpool, ConstantPool::resolved_klasses_offset_in_bytes())); // Rklass = cpool->_resolved_klasses + add(Rklass, Rklass, AsmOperand(Rtemp, lsl, LogBytesPerWord)); + ldr(Rklass, Address(Rklass, Array::base_offset_in_bytes())); +} + // Generate a subtype check: branch to not_subtype if sub_klass is // not a subtype of super_klass. // Profiling code for the subtype check failure (profile_typecheck_failed) @@ -2016,75 +2026,42 @@ void InterpreterMacroAssembler::increment_mask_and_jump(Address counter_addr, void InterpreterMacroAssembler::get_method_counters(Register method, Register Rcounters, - Label& skip) { + Label& skip, + bool saveRegs, + Register reg1, + Register reg2, + Register reg3) { const Address method_counters(method, Method::method_counters_offset()); Label has_counters; ldr(Rcounters, method_counters); cbnz(Rcounters, has_counters); + if (saveRegs) { + // Save and restore in use caller-saved registers since they will be trashed by call_VM + assert(reg1 != noreg, "must specify reg1"); + assert(reg2 != noreg, "must specify reg2"); #ifdef AARCH64 - const Register tmp = Rcounters; - const int saved_regs_size = 20*wordSize; - - // Note: call_VM will cut SP according to Rstack_top value before call, and restore SP to - // extended_sp value from frame after the call. - // So make sure there is enough stack space to save registers and adjust Rstack_top accordingly. - { - Label enough_stack_space; - check_extended_sp(tmp); - sub(Rstack_top, Rstack_top, saved_regs_size); - cmp(SP, Rstack_top); - b(enough_stack_space, ls); - - align_reg(tmp, Rstack_top, StackAlignmentInBytes); - mov(SP, tmp); - str(tmp, Address(FP, frame::interpreter_frame_extended_sp_offset * wordSize)); - - bind(enough_stack_space); - check_stack_top(); - - int offset = 0; - stp(R0, R1, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R2, R3, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R4, R5, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R6, R7, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R8, R9, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R10, R11, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R12, R13, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R14, R15, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R16, R17, Address(Rstack_top, offset)); offset += 2*wordSize; - stp(R18, LR, Address(Rstack_top, offset)); offset += 2*wordSize; - assert (offset == saved_regs_size, "should be"); - } + assert(reg3 != noreg, "must specify reg3"); + stp(reg1, reg2, Address(Rstack_top, -2*wordSize, pre_indexed)); + stp(reg3, ZR, Address(Rstack_top, -2*wordSize, pre_indexed)); #else - push(RegisterSet(R0, R3) | RegisterSet(R12) | RegisterSet(R14)); -#endif // AARCH64 + assert(reg3 == noreg, "must not specify reg3"); + push(RegisterSet(reg1) | RegisterSet(reg2)); +#endif + } mov(R1, method); - call_VM(noreg, CAST_FROM_FN_PTR(address, - InterpreterRuntime::build_method_counters), R1); + call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters), R1); + if (saveRegs) { #ifdef AARCH64 - { - int offset = 0; - ldp(R0, R1, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R2, R3, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R4, R5, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R6, R7, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R8, R9, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R10, R11, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R12, R13, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R14, R15, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R16, R17, Address(Rstack_top, offset)); offset += 2*wordSize; - ldp(R18, LR, Address(Rstack_top, offset)); offset += 2*wordSize; - assert (offset == saved_regs_size, "should be"); - - add(Rstack_top, Rstack_top, saved_regs_size); - } + ldp(reg3, ZR, Address(Rstack_top, 2*wordSize, post_indexed)); + ldp(reg1, reg2, Address(Rstack_top, 2*wordSize, post_indexed)); #else - pop(RegisterSet(R0, R3) | RegisterSet(R12) | RegisterSet(R14)); -#endif // AARCH64 + pop(RegisterSet(reg1) | RegisterSet(reg2)); +#endif + } ldr(Rcounters, method_counters); cbz(Rcounters, skip); // No MethodCounters created, OutOfMemory diff --git a/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp b/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp index 39e60226bf6..434f501bf74 100644 --- a/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp +++ b/hotspot/src/cpu/arm/vm/interp_masm_arm.hpp @@ -53,9 +53,6 @@ class InterpreterMacroAssembler: public MacroAssembler { // Template interpreter specific version of call_VM_helper virtual void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions); - virtual void check_and_handle_popframe(); - virtual void check_and_handle_earlyret(); - // base routine for all dispatches typedef enum { DispatchDefault, DispatchNormal } DispatchTableMode; void dispatch_base(TosState state, DispatchTableMode table_mode, bool verifyoop = true); @@ -63,6 +60,9 @@ class InterpreterMacroAssembler: public MacroAssembler { public: InterpreterMacroAssembler(CodeBuffer* code); + virtual void check_and_handle_popframe(); + virtual void check_and_handle_earlyret(); + // Interpreter-specific registers #if defined(AARCH64) && defined(ASSERT) @@ -141,6 +141,9 @@ class InterpreterMacroAssembler: public MacroAssembler { // Load object from cpool->resolved_references(*bcp+1) void load_resolved_reference_at_index(Register result, Register tmp); + // load cpool->resolved_klass_at(index); Rtemp is corrupted upon return + void load_resolved_klass_at_offset(Register Rcpool, Register Rindex, Register Rklass); + void store_check_part1(Register card_table_base); // Sets card_table_base register. void store_check_part2(Register obj, Register card_table_base, Register tmp); @@ -328,7 +331,13 @@ class InterpreterMacroAssembler: public MacroAssembler { void trace_state(const char* msg) PRODUCT_RETURN; - void get_method_counters(Register method, Register Rcounters, Label& skip); +void get_method_counters(Register method, + Register Rcounters, + Label& skip, + bool saveRegs = false, + Register reg1 = noreg, + Register reg2 = noreg, + Register reg3 = noreg); }; #endif // CPU_ARM_VM_INTERP_MASM_ARM_HPP diff --git a/hotspot/src/cpu/arm/vm/interpreterRT_arm.cpp b/hotspot/src/cpu/arm/vm/interpreterRT_arm.cpp index 4925f630c8d..af895ad91b4 100644 --- a/hotspot/src/cpu/arm/vm/interpreterRT_arm.cpp +++ b/hotspot/src/cpu/arm/vm/interpreterRT_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -422,7 +422,7 @@ class SlowSignatureHandler: public NativeSignatureIterator { #endif // !__ABI_HARD__ public: - SlowSignatureHandler(methodHandle method, address from, intptr_t* to) : + SlowSignatureHandler(const methodHandle& method, address from, intptr_t* to) : NativeSignatureIterator(method) { _from = from; diff --git a/hotspot/src/cpu/arm/vm/interpreterRT_arm.hpp b/hotspot/src/cpu/arm/vm/interpreterRT_arm.hpp index fa1e0dce678..28c8b3c7db2 100644 --- a/hotspot/src/cpu/arm/vm/interpreterRT_arm.hpp +++ b/hotspot/src/cpu/arm/vm/interpreterRT_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -56,7 +56,7 @@ class SignatureHandlerGenerator: public NativeSignatureIterator { #endif public: // Creation - SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) { + SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) { _masm = new MacroAssembler(buffer); _abi_offset = 0; _ireg = is_static() ? 2 : 1; diff --git a/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp b/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp index e6f73353cb9..b0710a1518a 100644 --- a/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp +++ b/hotspot/src/cpu/arm/vm/macroAssembler_arm.hpp @@ -206,6 +206,9 @@ protected: // may customize this version by overriding it for its purposes (e.g., to save/restore // additional registers when doing a VM call). virtual void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions); +public: + + MacroAssembler(CodeBuffer* code) : Assembler(code) {} // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. // The implementation is only non-empty for the InterpreterMacroAssembler, @@ -213,10 +216,6 @@ protected: virtual void check_and_handle_popframe() {} virtual void check_and_handle_earlyret() {} -public: - - MacroAssembler(CodeBuffer* code) : Assembler(code) {} - // By default, we do not need relocation information for non // patchable absolute addresses. However, when needed by some // extensions, ignore_non_patchable_relocations can be modified, diff --git a/hotspot/src/cpu/arm/vm/metaspaceShared_arm.cpp b/hotspot/src/cpu/arm/vm/metaspaceShared_arm.cpp deleted file mode 100644 index 1cda4dff24e..00000000000 --- a/hotspot/src/cpu/arm/vm/metaspaceShared_arm.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2008, 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 "asm/macroAssembler.hpp" -#include "assembler_arm.inline.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - for (int i = 0; i < vtbl_list_size; ++i) { - Label common_code; - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*) __ pc(); - __ mov(Rtemp, j); // Rtemp contains an index of a virtual method in the table - __ b(common_code); - } - - InlinedAddress vtable_address((address)&vtbl_list[i]); - __ bind(common_code); - const Register tmp2 = AARCH64_ONLY(Rtemp2) NOT_AARCH64(R4); - assert_different_registers(Rtemp, tmp2); -#ifndef AARCH64 - __ push(tmp2); -#endif // !AARCH64 - // Do not use ldr_global since the code must be portable across all ARM architectures - __ ldr_literal(tmp2, vtable_address); - __ ldr(tmp2, Address(tmp2)); // get correct vtable address - __ ldr(Rtemp, Address::indexed_ptr(tmp2, Rtemp)); // get real method pointer - __ str(tmp2, Address(R0)); // update vtable. R0 = "this" -#ifndef AARCH64 - __ pop(tmp2); -#endif // !AARCH64 - __ jump(Rtemp); - __ bind_literal(vtable_address); - } - - __ flush(); - *mc_top = (char*) __ pc(); -} diff --git a/hotspot/src/cpu/arm/vm/methodHandles_arm.cpp b/hotspot/src/cpu/arm/vm/methodHandles_arm.cpp index 15317969319..be9dac4de4f 100644 --- a/hotspot/src/cpu/arm/vm/methodHandles_arm.cpp +++ b/hotspot/src/cpu/arm/vm/methodHandles_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -32,6 +32,7 @@ #include "interpreter/interpreterRuntime.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" +#include "prims/jvm.h" #include "prims/methodHandles.hpp" #define __ _masm-> @@ -67,7 +68,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register obj, Register temp1, Register temp2, SystemDictionary::WKID klass_id, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); Label L_ok, L_bad; BLOCK_COMMENT("verify_klass {"); __ verify_oop(obj); @@ -157,8 +158,9 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, __ load_heap_oop(tmp, Address(tmp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()))); __ verify_oop(tmp); - // the following assumes that a Method* is normally compressed in the vmtarget field: - __ ldr(Rmethod, Address(tmp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()))); + __ load_heap_oop(Rmethod, Address(tmp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()))); + __ verify_oop(Rmethod); + __ ldr(Rmethod, Address(Rmethod, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()))); if (VerifyMethodHandles && !for_compiler_entry) { // make sure recv is already on stack @@ -320,7 +322,8 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes())); Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes())); - Address member_vmtarget(member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())); + Address member_vmtarget(member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())); + Address vmtarget_method(Rmethod, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())); Register temp1_recv_klass = temp1; if (iid != vmIntrinsics::_linkToStatic) { @@ -375,14 +378,17 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3); } - __ ldr(Rmethod, member_vmtarget); + __ load_heap_oop(Rmethod, member_vmtarget); + __ ldr(Rmethod, vmtarget_method); break; case vmIntrinsics::_linkToStatic: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3); } - __ ldr(Rmethod, member_vmtarget); + __ load_heap_oop(Rmethod, member_vmtarget); + __ ldr(Rmethod, vmtarget_method); + break; break; case vmIntrinsics::_linkToVirtual: diff --git a/hotspot/src/cpu/arm/vm/sharedRuntime_arm.cpp b/hotspot/src/cpu/arm/vm/sharedRuntime_arm.cpp index 48f096473c3..59bc2e5b5d8 100644 --- a/hotspot/src/cpu/arm/vm/sharedRuntime_arm.cpp +++ b/hotspot/src/cpu/arm/vm/sharedRuntime_arm.cpp @@ -34,6 +34,7 @@ #include "oops/compiledICHolder.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/align.hpp" #include "vmreg_arm.inline.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" @@ -747,7 +748,7 @@ void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm, assert_different_registers(tmp, R0, R1, R2, R3, R4, R5, R6, R7, Rsender_sp, Rparams); if (comp_args_on_stack) { - __ sub_slow(SP, SP, round_to(comp_args_on_stack * VMRegImpl::stack_slot_size, StackAlignmentInBytes)); + __ sub_slow(SP, SP, align_up(comp_args_on_stack * VMRegImpl::stack_slot_size, StackAlignmentInBytes)); } for (int i = 0; i < total_args_passed; i++) { @@ -870,7 +871,7 @@ static void gen_c2i_adapter(MacroAssembler *masm, #ifdef AARCH64 - int extraspace = round_to(total_args_passed * Interpreter::stackElementSize, StackAlignmentInBytes); + int extraspace = align_up(total_args_passed * Interpreter::stackElementSize, StackAlignmentInBytes); if (extraspace) { __ sub(SP, SP, extraspace); } @@ -1023,7 +1024,7 @@ static int reg2offset_out(VMReg r) { static void verify_oop_args(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, const BasicType* sig_bt, const VMRegPair* regs) { Register temp_reg = Rmethod; // not part of any compiled calling seq @@ -1044,7 +1045,7 @@ static void verify_oop_args(MacroAssembler* masm, } static void gen_special_dispatch(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, const BasicType* sig_bt, const VMRegPair* regs) { verify_oop_args(masm, method, sig_bt, regs); @@ -1181,7 +1182,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, stack_slots += 2 * VMRegImpl::slots_per_word; // Calculate the final stack size taking account of alignment - stack_slots = round_to(stack_slots, StackAlignmentInBytes / VMRegImpl::stack_slot_size); + stack_slots = align_up(stack_slots, StackAlignmentInBytes / VMRegImpl::stack_slot_size); int stack_size = stack_slots * VMRegImpl::stack_slot_size; int lock_slot_fp_offset = stack_size - 2 * wordSize - lock_slot_offset * VMRegImpl::stack_slot_size; @@ -1851,7 +1852,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals) { int extra_locals_size = (callee_locals - callee_parameters) * Interpreter::stackElementWords; #ifdef AARCH64 - extra_locals_size = round_to(extra_locals_size, StackAlignmentInBytes/BytesPerWord); + extra_locals_size = align_up(extra_locals_size, StackAlignmentInBytes/BytesPerWord); #endif // AARCH64 return extra_locals_size; } diff --git a/hotspot/src/cpu/arm/vm/stubGenerator_arm.cpp b/hotspot/src/cpu/arm/vm/stubGenerator_arm.cpp index 7d8c8d49927..d5ca6401fa4 100644 --- a/hotspot/src/cpu/arm/vm/stubGenerator_arm.cpp +++ b/hotspot/src/cpu/arm/vm/stubGenerator_arm.cpp @@ -37,6 +37,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" +#include "utilities/align.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" #endif @@ -2876,7 +2877,7 @@ class StubGenerator: public StubCodeGenerator { BLOCK_COMMENT("PreBarrier"); #ifdef AARCH64 - callee_saved_regs = round_to(callee_saved_regs, 2); + callee_saved_regs = align_up(callee_saved_regs, 2); for (int i = 0; i < callee_saved_regs; i += 2) { __ raw_push(as_Register(i), as_Register(i+1)); } diff --git a/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp b/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp index 7fda747ad48..1c2e706a26c 100644 --- a/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp +++ b/hotspot/src/cpu/arm/vm/templateInterpreterGenerator_arm.cpp @@ -45,6 +45,7 @@ #include "runtime/synchronizer.hpp" #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/align.hpp" #include "utilities/debug.hpp" #include "utilities/macros.hpp" @@ -270,12 +271,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch return entry; } -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - // Not used. - STOP("generate_continuation_for"); - return NULL; -} - address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address entry = __ pc(); @@ -310,6 +305,9 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ convert_retval_to_tos(state); #endif // !AARCH64 + __ check_and_handle_popframe(); + __ check_and_handle_earlyret(); + __ dispatch_next(state, step); return entry; @@ -678,7 +676,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { // Rstack_top & RextendedSP __ sub(Rstack_top, SP, 10*wordSize); if (native_call) { - __ sub(RextendedSP, Rstack_top, round_to(wordSize, StackAlignmentInBytes)); // reserve 1 slot for exception handling + __ sub(RextendedSP, Rstack_top, align_up(wordSize, StackAlignmentInBytes)); // reserve 1 slot for exception handling } else { __ sub(RextendedSP, Rstack_top, AsmOperand(RmaxStack, lsl, Interpreter::logStackElementSize)); __ align_reg(RextendedSP, RextendedSP, StackAlignmentInBytes); @@ -1098,7 +1096,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // Allocate more stack space to accomodate all arguments passed on GP and FP registers: // 8 * wordSize for GPRs // 8 * wordSize for FPRs - int reg_arguments = round_to(8*wordSize + 8*wordSize, StackAlignmentInBytes); + int reg_arguments = align_up(8*wordSize + 8*wordSize, StackAlignmentInBytes); #else // C functions need aligned stack @@ -1111,7 +1109,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // Allocate more stack space to accomodate all GP as well as FP registers: // 4 * wordSize // 8 * BytesPerLong - int reg_arguments = round_to((4*wordSize) + (8*BytesPerLong), StackAlignmentInBytes); + int reg_arguments = align_up((4*wordSize) + (8*BytesPerLong), StackAlignmentInBytes); #else // Reserve at least 4 words on the stack for loading // of parameters passed on registers (R0-R3). @@ -1401,7 +1399,13 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { #ifdef AARCH64 // setup RmaxStack __ ldrh(RmaxStack, Address(RconstMethod, ConstMethod::max_stack_offset())); - __ add(RmaxStack, RmaxStack, MAX2(1, Method::extra_stack_entries())); // reserve slots for exception handler and JSR292 appendix argument + // We have to add extra reserved slots to max_stack. There are 3 users of the extra slots, + // none of which are at the same time, so we just need to make sure there is enough room + // for the biggest user: + // -reserved slot for exception handler + // -reserved slots for JSR292. Method::extra_stack_entries() is the size. + // -3 reserved slots so get_method_counters() can save some registers before call_VM(). + __ add(RmaxStack, RmaxStack, MAX2(3, Method::extra_stack_entries())); #endif // AARCH64 // see if we've got enough room on the stack for locals plus overhead. diff --git a/hotspot/src/cpu/arm/vm/templateTable_arm.cpp b/hotspot/src/cpu/arm/vm/templateTable_arm.cpp index c8711b830eb..7fd60ce8d2d 100644 --- a/hotspot/src/cpu/arm/vm/templateTable_arm.cpp +++ b/hotspot/src/cpu/arm/vm/templateTable_arm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -2286,13 +2286,18 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { } __ bind(no_mdo); // Increment backedge counter in MethodCounters* - __ get_method_counters(Rmethod, Rcounters, dispatch); + // Note Rbumped_taken_count is a callee saved registers for ARM32, but caller saved for ARM64 + __ get_method_counters(Rmethod, Rcounters, dispatch, true /*saveRegs*/, + Rdisp, R3_bytecode, + AARCH64_ONLY(Rbumped_taken_count) NOT_AARCH64(noreg)); const Address mask(Rcounters, in_bytes(MethodCounters::backedge_mask_offset())); __ increment_mask_and_jump(Address(Rcounters, be_offset), increment, mask, Rcnt, R4_tmp, eq, &backedge_counter_overflow); } else { - // increment counter - __ get_method_counters(Rmethod, Rcounters, dispatch); + // Increment backedge counter in MethodCounters* + __ get_method_counters(Rmethod, Rcounters, dispatch, true /*saveRegs*/, + Rdisp, R3_bytecode, + AARCH64_ONLY(Rbumped_taken_count) NOT_AARCH64(noreg)); __ ldr_u32(Rtemp, Address(Rcounters, be_offset)); // load backedge counter __ add(Rtemp, Rtemp, InvocationCounter::count_increment); // increment counter __ str_32(Rtemp, Address(Rcounters, be_offset)); // store counter @@ -4367,10 +4372,9 @@ void TemplateTable::_new() { #endif // AARCH64 // get InstanceKlass - __ add(Rklass, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord)); - __ ldr(Rklass, Address(Rklass, sizeof(ConstantPool))); __ cmp(Rtemp, JVM_CONSTANT_Class); __ b(slow_case, ne); + __ load_resolved_klass_at_offset(Rcpool, Rindex, Rklass); // make sure klass is initialized & doesn't have finalizer // make sure klass is fully initialized @@ -4642,8 +4646,7 @@ void TemplateTable::checkcast() { // Get superklass in Rsuper and subklass in Rsub __ bind(quicked); - __ add(Rtemp, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord)); - __ ldr(Rsuper, Address(Rtemp, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(Rcpool, Rindex, Rsuper); __ bind(resolved); __ load_klass(Rsub, Robj); @@ -4716,8 +4719,7 @@ void TemplateTable::instanceof() { // Get superklass in Rsuper and subklass in Rsub __ bind(quicked); - __ add(Rtemp, Rcpool, AsmOperand(Rindex, lsl, LogBytesPerWord)); - __ ldr(Rsuper, Address(Rtemp, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(Rcpool, Rindex, Rsuper); __ bind(resolved); __ load_klass(Rsub, Robj); diff --git a/hotspot/src/cpu/arm/vm/vm_version_arm_32.cpp b/hotspot/src/cpu/arm/vm/vm_version_arm_32.cpp index 10a2408772d..2d1d4949860 100644 --- a/hotspot/src/cpu/arm/vm/vm_version_arm_32.cpp +++ b/hotspot/src/cpu/arm/vm/vm_version_arm_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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,6 +25,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" #include "memory/resourceArea.hpp" +#include "prims/jvm.h" #include "runtime/java.hpp" #include "runtime/os.inline.hpp" #include "runtime/stubCodeGenerator.hpp" @@ -256,7 +257,9 @@ void VM_Version::initialize() { } } - AllocatePrefetchDistance = 128; + if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) { + FLAG_SET_DEFAULT(AllocatePrefetchDistance, 128); + } #ifdef COMPILER2 FLAG_SET_DEFAULT(UseFPUForSpilling, true); diff --git a/hotspot/src/cpu/arm/vm/vm_version_arm_64.cpp b/hotspot/src/cpu/arm/vm/vm_version_arm_64.cpp index 7f25255d72f..55091befc78 100644 --- a/hotspot/src/cpu/arm/vm/vm_version_arm_64.cpp +++ b/hotspot/src/cpu/arm/vm/vm_version_arm_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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,6 +25,7 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" #include "memory/resourceArea.hpp" +#include "prims/jvm.h" #include "runtime/java.hpp" #include "runtime/os.inline.hpp" #include "runtime/stubCodeGenerator.hpp" @@ -201,7 +202,9 @@ void VM_Version::initialize() { } } - AllocatePrefetchDistance = 128; + if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) { + FLAG_SET_DEFAULT(AllocatePrefetchDistance, 128); + } #ifdef COMPILER2 FLAG_SET_DEFAULT(UseFPUForSpilling, true); diff --git a/hotspot/src/cpu/ppc/vm/abstractInterpreter_ppc.cpp b/hotspot/src/cpu/ppc/vm/abstractInterpreter_ppc.cpp index 9aa1370a362..44dd1608d65 100644 --- a/hotspot/src/cpu/ppc/vm/abstractInterpreter_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/abstractInterpreter_ppc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -51,27 +51,6 @@ int AbstractInterpreter::BasicType_as_index(BasicType type) { return i; } -// These should never be compiled since the interpreter will prefer -// the compiled version to the intrinsic version. -bool AbstractInterpreter::can_be_compiled(methodHandle m) { - switch (method_kind(m)) { - case Interpreter::java_lang_math_sin : // fall thru - case Interpreter::java_lang_math_cos : // fall thru - case Interpreter::java_lang_math_tan : // fall thru - case Interpreter::java_lang_math_abs : // fall thru - case Interpreter::java_lang_math_log : // fall thru - case Interpreter::java_lang_math_log10 : // fall thru - case Interpreter::java_lang_math_sqrt : // fall thru - case Interpreter::java_lang_math_pow : // fall thru - case Interpreter::java_lang_math_exp : // fall thru - case Interpreter::java_lang_math_fmaD : // fall thru - case Interpreter::java_lang_math_fmaF : - return false; - default: - return true; - } -} - // How much stack a method activation needs in stack slots. // We must calc this exactly like in generate_fixed_frame. // Note: This returns the conservative size assuming maximum alignment. diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp index 09217a42bb5..26b77b8cbc3 100644 --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 SAP SE. 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 @@ -376,10 +376,12 @@ class Assembler : public AbstractAssembler { STWX_OPCODE = (31u << OPCODE_SHIFT | 151u << 1), STWU_OPCODE = (37u << OPCODE_SHIFT), STWUX_OPCODE = (31u << OPCODE_SHIFT | 183u << 1), + STWBRX_OPCODE = (31u << OPCODE_SHIFT | 662u << 1), STH_OPCODE = (44u << OPCODE_SHIFT), STHX_OPCODE = (31u << OPCODE_SHIFT | 407u << 1), STHU_OPCODE = (45u << OPCODE_SHIFT), + STHBRX_OPCODE = (31u << OPCODE_SHIFT | 918u << 1), STB_OPCODE = (38u << OPCODE_SHIFT), STBX_OPCODE = (31u << OPCODE_SHIFT | 215u << 1), @@ -401,11 +403,13 @@ class Assembler : public AbstractAssembler { LD_OPCODE = (58u << OPCODE_SHIFT | 0u << XO_30_31_SHIFT), // DS-FORM LDU_OPCODE = (58u << OPCODE_SHIFT | 1u << XO_30_31_SHIFT), // DS-FORM LDX_OPCODE = (31u << OPCODE_SHIFT | 21u << XO_21_30_SHIFT), // X-FORM + LDBRX_OPCODE = (31u << OPCODE_SHIFT | 532u << 1), // X-FORM STD_OPCODE = (62u << OPCODE_SHIFT | 0u << XO_30_31_SHIFT), // DS-FORM STDU_OPCODE = (62u << OPCODE_SHIFT | 1u << XO_30_31_SHIFT), // DS-FORM - STDUX_OPCODE = (31u << OPCODE_SHIFT | 181u << 1), // X-FORM + STDUX_OPCODE = (31u << OPCODE_SHIFT | 181u << 1), // X-FORM STDX_OPCODE = (31u << OPCODE_SHIFT | 149u << XO_21_30_SHIFT), // X-FORM + STDBRX_OPCODE = (31u << OPCODE_SHIFT | 660u << 1), // X-FORM RLDICR_OPCODE = (30u << OPCODE_SHIFT | 1u << XO_27_29_SHIFT), // MD-FORM RLDICL_OPCODE = (30u << OPCODE_SHIFT | 0u << XO_27_29_SHIFT), // MD-FORM @@ -506,7 +510,13 @@ class Assembler : public AbstractAssembler { LXVD2X_OPCODE = (31u << OPCODE_SHIFT | 844u << 1), STXVD2X_OPCODE = (31u << OPCODE_SHIFT | 972u << 1), MTVSRD_OPCODE = (31u << OPCODE_SHIFT | 179u << 1), + MTVSRWZ_OPCODE = (31u << OPCODE_SHIFT | 243u << 1), MFVSRD_OPCODE = (31u << OPCODE_SHIFT | 51u << 1), + MTVSRWA_OPCODE = (31u << OPCODE_SHIFT | 211u << 1), + MFVSRWZ_OPCODE = (31u << OPCODE_SHIFT | 115u << 1), + XXPERMDI_OPCODE= (60u << OPCODE_SHIFT | 10u << 3), + XXMRGHW_OPCODE = (60u << OPCODE_SHIFT | 18u << 3), + XXMRGLW_OPCODE = (60u << OPCODE_SHIFT | 50u << 3), // Vector Permute and Formatting VPKPX_OPCODE = (4u << OPCODE_SHIFT | 782u ), @@ -556,6 +566,7 @@ class Assembler : public AbstractAssembler { VADDUBM_OPCODE = (4u << OPCODE_SHIFT | 0u ), VADDUWM_OPCODE = (4u << OPCODE_SHIFT | 128u ), VADDUHM_OPCODE = (4u << OPCODE_SHIFT | 64u ), + VADDUDM_OPCODE = (4u << OPCODE_SHIFT | 192u ), VADDUBS_OPCODE = (4u << OPCODE_SHIFT | 512u ), VADDUWS_OPCODE = (4u << OPCODE_SHIFT | 640u ), VADDUHS_OPCODE = (4u << OPCODE_SHIFT | 576u ), @@ -1094,16 +1105,19 @@ class Assembler : public AbstractAssembler { static int vrs( VectorRegister r) { return vrs(r->encoding());} static int vrt( VectorRegister r) { return vrt(r->encoding());} + // Only used on SHA sigma instructions (VX-form) + static int vst( int x) { return opp_u_field(x, 16, 16); } + static int vsix( int x) { return opp_u_field(x, 20, 17); } + // Support Vector-Scalar (VSX) instructions. - static int vsra( int x) { return opp_u_field(x, 15, 11); } - static int vsrb( int x) { return opp_u_field(x, 20, 16); } - static int vsrc( int x) { return opp_u_field(x, 25, 21); } - static int vsrs( int x) { return opp_u_field(x, 10, 6); } - static int vsrt( int x) { return opp_u_field(x, 10, 6); } + static int vsra( int x) { return opp_u_field(x & 0x1F, 15, 11) | opp_u_field((x & 0x20) >> 5, 29, 29); } + static int vsrb( int x) { return opp_u_field(x & 0x1F, 20, 16) | opp_u_field((x & 0x20) >> 5, 30, 30); } + static int vsrs( int x) { return opp_u_field(x & 0x1F, 10, 6) | opp_u_field((x & 0x20) >> 5, 31, 31); } + static int vsrt( int x) { return vsrs(x); } + static int vsdm( int x) { return opp_u_field(x, 23, 22); } static int vsra( VectorSRegister r) { return vsra(r->encoding());} static int vsrb( VectorSRegister r) { return vsrb(r->encoding());} - static int vsrc( VectorSRegister r) { return vsrc(r->encoding());} static int vsrs( VectorSRegister r) { return vsrs(r->encoding());} static int vsrt( VectorSRegister r) { return vsrt(r->encoding());} @@ -1552,6 +1566,9 @@ class Assembler : public AbstractAssembler { inline void ld( Register d, int si16, Register s1); inline void ldu( Register d, int si16, Register s1); + // 8 bytes reversed + inline void ldbrx( Register d, Register s1, Register s2); + // For convenience. Load pointer into d from b+s1. inline void ld_ptr(Register d, int b, Register s1); DEBUG_ONLY(inline void ld_ptr(Register d, ByteSize b, Register s1);) @@ -1560,10 +1577,12 @@ class Assembler : public AbstractAssembler { inline void stwx( Register d, Register s1, Register s2); inline void stw( Register d, int si16, Register s1); inline void stwu( Register d, int si16, Register s1); + inline void stwbrx( Register d, Register s1, Register s2); inline void sthx( Register d, Register s1, Register s2); inline void sth( Register d, int si16, Register s1); inline void sthu( Register d, int si16, Register s1); + inline void sthbrx( Register d, Register s1, Register s2); inline void stbx( Register d, Register s1, Register s2); inline void stb( Register d, int si16, Register s1); @@ -1573,6 +1592,7 @@ class Assembler : public AbstractAssembler { inline void std( Register d, int si16, Register s1); inline void stdu( Register d, int si16, Register s1); inline void stdux(Register s, Register a, Register b); + inline void stdbrx( Register d, Register s1, Register s2); inline void st_ptr(Register d, int si16, Register s1); DEBUG_ONLY(inline void st_ptr(Register d, ByteSize b, Register s1);) @@ -2016,7 +2036,7 @@ class Assembler : public AbstractAssembler { inline void vperm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); inline void vsel( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); inline void vsl( VectorRegister d, VectorRegister a, VectorRegister b); - inline void vsldoi( VectorRegister d, VectorRegister a, VectorRegister b, int si4); + inline void vsldoi( VectorRegister d, VectorRegister a, VectorRegister b, int ui4); inline void vslo( VectorRegister d, VectorRegister a, VectorRegister b); inline void vsr( VectorRegister d, VectorRegister a, VectorRegister b); inline void vsro( VectorRegister d, VectorRegister a, VectorRegister b); @@ -2027,6 +2047,7 @@ class Assembler : public AbstractAssembler { inline void vaddubm( VectorRegister d, VectorRegister a, VectorRegister b); inline void vadduwm( VectorRegister d, VectorRegister a, VectorRegister b); inline void vadduhm( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vaddudm( VectorRegister d, VectorRegister a, VectorRegister b); inline void vaddubs( VectorRegister d, VectorRegister a, VectorRegister b); inline void vadduws( VectorRegister d, VectorRegister a, VectorRegister b); inline void vadduhs( VectorRegister d, VectorRegister a, VectorRegister b); @@ -2102,6 +2123,7 @@ class Assembler : public AbstractAssembler { inline void vandc( VectorRegister d, VectorRegister a, VectorRegister b); inline void vnor( VectorRegister d, VectorRegister a, VectorRegister b); inline void vor( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vmr( VectorRegister d, VectorRegister a); inline void vxor( VectorRegister d, VectorRegister a, VectorRegister b); inline void vrld( VectorRegister d, VectorRegister a, VectorRegister b); inline void vrlb( VectorRegister d, VectorRegister a, VectorRegister b); @@ -2125,8 +2147,24 @@ class Assembler : public AbstractAssembler { inline void lxvd2x( VectorSRegister d, Register a, Register b); inline void stxvd2x( VectorSRegister d, Register a); inline void stxvd2x( VectorSRegister d, Register a, Register b); + inline void mtvrwz( VectorRegister d, Register a); + inline void mfvrwz( Register a, VectorRegister d); inline void mtvrd( VectorRegister d, Register a); inline void mfvrd( Register a, VectorRegister d); + inline void xxpermdi( VectorSRegister d, VectorSRegister a, VectorSRegister b, int dm); + inline void xxmrghw( VectorSRegister d, VectorSRegister a, VectorSRegister b); + inline void xxmrglw( VectorSRegister d, VectorSRegister a, VectorSRegister b); + + // VSX Extended Mnemonics + inline void xxspltd( VectorSRegister d, VectorSRegister a, int x); + inline void xxmrghd( VectorSRegister d, VectorSRegister a, VectorSRegister b); + inline void xxmrgld( VectorSRegister d, VectorSRegister a, VectorSRegister b); + inline void xxswapd( VectorSRegister d, VectorSRegister a); + + // Vector-Scalar (VSX) instructions. + inline void mtfprd( FloatRegister d, Register a); + inline void mtfprwa( FloatRegister d, Register a); + inline void mffprd( Register a, FloatRegister d); // AES (introduced with Power 8) inline void vcipher( VectorRegister d, VectorRegister a, VectorRegister b); @@ -2182,14 +2220,18 @@ class Assembler : public AbstractAssembler { inline void lbz( Register d, int si16); inline void ldx( Register d, Register s2); inline void ld( Register d, int si16); + inline void ldbrx(Register d, Register s2); inline void stwx( Register d, Register s2); inline void stw( Register d, int si16); + inline void stwbrx( Register d, Register s2); inline void sthx( Register d, Register s2); inline void sth( Register d, int si16); + inline void sthbrx( Register d, Register s2); inline void stbx( Register d, Register s2); inline void stb( Register d, int si16); inline void stdx( Register d, Register s2); inline void std( Register d, int si16); + inline void stdbrx( Register d, Register s2); // PPC 2, section 3.2.1 Instruction Cache Instructions inline void icbi( Register s2); diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp index 7f42d6b6050..d21ffaf8fcb 100644 --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 SAP SE. 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 @@ -327,6 +327,7 @@ inline void Assembler::lbzu( Register d, int si16, Register s1) { assert(d != inline void Assembler::ld( Register d, int si16, Register s1) { emit_int32(LD_OPCODE | rt(d) | ds(si16) | ra0mem(s1));} inline void Assembler::ldx( Register d, Register s1, Register s2) { emit_int32(LDX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} inline void Assembler::ldu( Register d, int si16, Register s1) { assert(d != s1, "according to ibm manual"); emit_int32(LDU_OPCODE | rt(d) | ds(si16) | rta0mem(s1));} +inline void Assembler::ldbrx( Register d, Register s1, Register s2) { emit_int32(LDBRX_OPCODE | rt(d) | ra0mem(s1) | rb(s2));} inline void Assembler::ld_ptr(Register d, int b, Register s1) { ld(d, b, s1); } DEBUG_ONLY(inline void Assembler::ld_ptr(Register d, ByteSize b, Register s1) { ld(d, in_bytes(b), s1); }) @@ -335,10 +336,12 @@ DEBUG_ONLY(inline void Assembler::ld_ptr(Register d, ByteSize b, Register s1) { inline void Assembler::stwx( Register d, Register s1, Register s2) { emit_int32(STWX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::stw( Register d, int si16, Register s1) { emit_int32(STW_OPCODE | rs(d) | d1(si16) | ra0mem(s1));} inline void Assembler::stwu( Register d, int si16, Register s1) { emit_int32(STWU_OPCODE | rs(d) | d1(si16) | rta0mem(s1));} +inline void Assembler::stwbrx( Register d, Register s1, Register s2) { emit_int32(STWBRX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::sthx( Register d, Register s1, Register s2) { emit_int32(STHX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::sth( Register d, int si16, Register s1) { emit_int32(STH_OPCODE | rs(d) | d1(si16) | ra0mem(s1));} inline void Assembler::sthu( Register d, int si16, Register s1) { emit_int32(STHU_OPCODE | rs(d) | d1(si16) | rta0mem(s1));} +inline void Assembler::sthbrx( Register d, Register s1, Register s2) { emit_int32(STHBRX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::stbx( Register d, Register s1, Register s2) { emit_int32(STBX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::stb( Register d, int si16, Register s1) { emit_int32(STB_OPCODE | rs(d) | d1(si16) | ra0mem(s1));} @@ -348,6 +351,7 @@ inline void Assembler::std( Register d, int si16, Register s1) { emit_int32( inline void Assembler::stdx( Register d, Register s1, Register s2) { emit_int32(STDX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::stdu( Register d, int si16, Register s1) { emit_int32(STDU_OPCODE | rs(d) | ds(si16) | rta0mem(s1));} inline void Assembler::stdux(Register s, Register a, Register b) { emit_int32(STDUX_OPCODE| rs(s) | rta0mem(a) | rb(b));} +inline void Assembler::stdbrx( Register d, Register s1, Register s2) { emit_int32(STDBRX_OPCODE | rs(d) | ra0mem(s1) | rb(s2));} inline void Assembler::st_ptr(Register d, int b, Register s1) { std(d, b, s1); } DEBUG_ONLY(inline void Assembler::st_ptr(Register d, ByteSize b, Register s1) { std(d, in_bytes(b), s1); }) @@ -754,12 +758,28 @@ inline void Assembler::lvsl( VectorRegister d, Register s1, Register s2) { emit inline void Assembler::lvsr( VectorRegister d, Register s1, Register s2) { emit_int32( LVSR_OPCODE | vrt(d) | ra0mem(s1) | rb(s2)); } // Vector-Scalar (VSX) instructions. -inline void Assembler::lxvd2x (VectorSRegister d, Register s1) { emit_int32( LXVD2X_OPCODE | vsrt(d) | ra(0) | rb(s1)); } -inline void Assembler::lxvd2x (VectorSRegister d, Register s1, Register s2) { emit_int32( LXVD2X_OPCODE | vsrt(d) | ra0mem(s1) | rb(s2)); } -inline void Assembler::stxvd2x(VectorSRegister d, Register s1) { emit_int32( STXVD2X_OPCODE | vsrt(d) | ra(0) | rb(s1)); } -inline void Assembler::stxvd2x(VectorSRegister d, Register s1, Register s2) { emit_int32( STXVD2X_OPCODE | vsrt(d) | ra0mem(s1) | rb(s2)); } -inline void Assembler::mtvrd( VectorRegister d, Register a) { emit_int32( MTVSRD_OPCODE | vrt(d) | ra(a) | 1u); } // 1u: d is treated as Vector (VMX/Altivec). -inline void Assembler::mfvrd( Register a, VectorRegister d) { emit_int32( MFVSRD_OPCODE | vrt(d) | ra(a) | 1u); } // 1u: d is treated as Vector (VMX/Altivec). +inline void Assembler::lxvd2x( VectorSRegister d, Register s1) { emit_int32( LXVD2X_OPCODE | vsrt(d) | ra(0) | rb(s1)); } +inline void Assembler::lxvd2x( VectorSRegister d, Register s1, Register s2) { emit_int32( LXVD2X_OPCODE | vsrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::stxvd2x( VectorSRegister d, Register s1) { emit_int32( STXVD2X_OPCODE | vsrt(d) | ra(0) | rb(s1)); } +inline void Assembler::stxvd2x( VectorSRegister d, Register s1, Register s2) { emit_int32( STXVD2X_OPCODE | vsrt(d) | ra0mem(s1) | rb(s2)); } +inline void Assembler::mtvrd( VectorRegister d, Register a) { emit_int32( MTVSRD_OPCODE | vsrt(d->to_vsr()) | ra(a)); } +inline void Assembler::mfvrd( Register a, VectorRegister d) { emit_int32( MFVSRD_OPCODE | vsrt(d->to_vsr()) | ra(a)); } +inline void Assembler::mtvrwz( VectorRegister d, Register a) { emit_int32( MTVSRWZ_OPCODE | vsrt(d->to_vsr()) | ra(a)); } +inline void Assembler::mfvrwz( Register a, VectorRegister d) { emit_int32( MFVSRWZ_OPCODE | vsrt(d->to_vsr()) | ra(a)); } +inline void Assembler::xxpermdi(VectorSRegister d, VectorSRegister a, VectorSRegister b, int dm) { emit_int32( XXPERMDI_OPCODE | vsrt(d) | vsra(a) | vsrb(b) | vsdm(dm)); } +inline void Assembler::xxmrghw( VectorSRegister d, VectorSRegister a, VectorSRegister b) { emit_int32( XXMRGHW_OPCODE | vsrt(d) | vsra(a) | vsrb(b)); } +inline void Assembler::xxmrglw( VectorSRegister d, VectorSRegister a, VectorSRegister b) { emit_int32( XXMRGHW_OPCODE | vsrt(d) | vsra(a) | vsrb(b)); } + +// VSX Extended Mnemonics +inline void Assembler::xxspltd( VectorSRegister d, VectorSRegister a, int x) { xxpermdi(d, a, a, x ? 3 : 0); } +inline void Assembler::xxmrghd( VectorSRegister d, VectorSRegister a, VectorSRegister b) { xxpermdi(d, a, b, 0); } +inline void Assembler::xxmrgld( VectorSRegister d, VectorSRegister a, VectorSRegister b) { xxpermdi(d, a, b, 3); } +inline void Assembler::xxswapd( VectorSRegister d, VectorSRegister a) { xxpermdi(d, a, a, 2); } + +// Vector-Scalar (VSX) instructions. +inline void Assembler::mtfprd( FloatRegister d, Register a) { emit_int32( MTVSRD_OPCODE | frt(d) | ra(a)); } +inline void Assembler::mtfprwa( FloatRegister d, Register a) { emit_int32( MTVSRWA_OPCODE | frt(d) | ra(a)); } +inline void Assembler::mffprd( Register a, FloatRegister d) { emit_int32( MFVSRD_OPCODE | frt(d) | ra(a)); } inline void Assembler::vpkpx( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKPX_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vpkshss( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPKSHSS_OPCODE | vrt(d) | vra(a) | vrb(b)); } @@ -791,7 +811,7 @@ inline void Assembler::vspltisw(VectorRegister d, int si5) inline void Assembler::vperm( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c){ emit_int32( VPERM_OPCODE | vrt(d) | vra(a) | vrb(b) | vrc(c)); } inline void Assembler::vsel( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c){ emit_int32( VSEL_OPCODE | vrt(d) | vra(a) | vrb(b) | vrc(c)); } inline void Assembler::vsl( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSL_OPCODE | vrt(d) | vra(a) | vrb(b)); } -inline void Assembler::vsldoi( VectorRegister d, VectorRegister a, VectorRegister b, int si4) { emit_int32( VSLDOI_OPCODE| vrt(d) | vra(a) | vrb(b) | vsldoi_shb(simm(si4,4))); } +inline void Assembler::vsldoi( VectorRegister d, VectorRegister a, VectorRegister b, int ui4) { emit_int32( VSLDOI_OPCODE| vrt(d) | vra(a) | vrb(b) | vsldoi_shb(uimm(ui4,4))); } inline void Assembler::vslo( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSLO_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vsr( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSR_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vsro( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VSRO_OPCODE | vrt(d) | vra(a) | vrb(b)); } @@ -802,6 +822,7 @@ inline void Assembler::vaddsws( VectorRegister d, VectorRegister a, VectorRegist inline void Assembler::vaddubm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUBM_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vadduwm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUWM_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vadduhm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUHM_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vaddudm( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUDM_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vaddubs( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUBS_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vadduws( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUWS_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vadduhs( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VADDUHS_OPCODE | vrt(d) | vra(a) | vrb(b)); } @@ -878,6 +899,7 @@ inline void Assembler::vand( VectorRegister d, VectorRegister a, VectorRegist inline void Assembler::vandc( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VANDC_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vnor( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VNOR_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vor( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VOR_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vmr( VectorRegister d, VectorRegister a) { emit_int32( VOR_OPCODE | vrt(d) | vra(a) | vrb(a)); } inline void Assembler::vxor( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VXOR_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vrld( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VRLD_OPCODE | vrt(d) | vra(a) | vrb(b)); } inline void Assembler::vrlb( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VRLB_OPCODE | vrt(d) | vra(a) | vrb(b)); } @@ -944,14 +966,18 @@ inline void Assembler::lbzx( Register d, Register s2) { emit_int32( LBZX_OPCODE inline void Assembler::lbz( Register d, int si16 ) { emit_int32( LBZ_OPCODE | rt(d) | d1(si16));} inline void Assembler::ld( Register d, int si16 ) { emit_int32( LD_OPCODE | rt(d) | ds(si16));} inline void Assembler::ldx( Register d, Register s2) { emit_int32( LDX_OPCODE | rt(d) | rb(s2));} +inline void Assembler::ldbrx(Register d, Register s2) { emit_int32( LDBRX_OPCODE| rt(d) | rb(s2));} inline void Assembler::stwx( Register d, Register s2) { emit_int32( STWX_OPCODE | rs(d) | rb(s2));} inline void Assembler::stw( Register d, int si16 ) { emit_int32( STW_OPCODE | rs(d) | d1(si16));} +inline void Assembler::stwbrx(Register d, Register s2){ emit_int32(STWBRX_OPCODE| rs(d) | rb(s2));} inline void Assembler::sthx( Register d, Register s2) { emit_int32( STHX_OPCODE | rs(d) | rb(s2));} inline void Assembler::sth( Register d, int si16 ) { emit_int32( STH_OPCODE | rs(d) | d1(si16));} +inline void Assembler::sthbrx(Register d, Register s2){ emit_int32(STHBRX_OPCODE| rs(d) | rb(s2));} inline void Assembler::stbx( Register d, Register s2) { emit_int32( STBX_OPCODE | rs(d) | rb(s2));} inline void Assembler::stb( Register d, int si16 ) { emit_int32( STB_OPCODE | rs(d) | d1(si16));} inline void Assembler::std( Register d, int si16 ) { emit_int32( STD_OPCODE | rs(d) | ds(si16));} inline void Assembler::stdx( Register d, Register s2) { emit_int32( STDX_OPCODE | rs(d) | rb(s2));} +inline void Assembler::stdbrx(Register d, Register s2){ emit_int32(STDBRX_OPCODE| rs(d) | rb(s2));} // ra0 version inline void Assembler::icbi( Register s2) { emit_int32( ICBI_OPCODE | rb(s2) ); } diff --git a/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp b/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp index b75b0f0fa5d..ac16dcb872d 100644 --- a/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/bytes_ppc.hpp @@ -37,10 +37,6 @@ class Bytes: AllStatic { #if defined(VM_LITTLE_ENDIAN) - // Returns true, if the byte ordering used by Java is different from the native byte ordering - // of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc. - static inline bool is_Java_byte_ordering_different() { return true; } - // Forward declarations of the compiler-dependent implementation static inline u2 swap_u2(u2 x); static inline u4 swap_u4(u4 x); @@ -155,10 +151,6 @@ class Bytes: AllStatic { #else // !defined(VM_LITTLE_ENDIAN) - // Returns true, if the byte ordering used by Java is different from the nativ byte ordering - // of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc. - static inline bool is_Java_byte_ordering_different() { return false; } - // Thus, a swap between native and Java ordering is always a no-op: static inline u2 swap_u2(u2 x) { return x; } static inline u4 swap_u4(u4 x) { return x; } diff --git a/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp index 127403fde2f..62be4f4820b 100644 --- a/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/c1_LIRAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, SAP SE. 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 @@ -514,25 +514,48 @@ void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { } case Bytecodes::_i2d: case Bytecodes::_l2d: { - __ fcfid(dst->as_double_reg(), src->as_double_reg()); // via mem + bool src_in_memory = !VM_Version::has_mtfprd(); + FloatRegister rdst = dst->as_double_reg(); + FloatRegister rsrc; + if (src_in_memory) { + rsrc = src->as_double_reg(); // via mem + } else { + // move src to dst register + if (code == Bytecodes::_i2d) { + __ mtfprwa(rdst, src->as_register()); + } else { + __ mtfprd(rdst, src->as_register_lo()); + } + rsrc = rdst; + } + __ fcfid(rdst, rsrc); break; } - case Bytecodes::_i2f: { + case Bytecodes::_i2f: + case Bytecodes::_l2f: { + bool src_in_memory = !VM_Version::has_mtfprd(); FloatRegister rdst = dst->as_float_reg(); - FloatRegister rsrc = src->as_double_reg(); // via mem + FloatRegister rsrc; + if (src_in_memory) { + rsrc = src->as_double_reg(); // via mem + } else { + // move src to dst register + if (code == Bytecodes::_i2f) { + __ mtfprwa(rdst, src->as_register()); + } else { + __ mtfprd(rdst, src->as_register_lo()); + } + rsrc = rdst; + } if (VM_Version::has_fcfids()) { __ fcfids(rdst, rsrc); } else { + assert(code == Bytecodes::_i2f, "fcfid+frsp needs fixup code to avoid rounding incompatibility"); __ fcfid(rdst, rsrc); __ frsp(rdst, rdst); } break; } - case Bytecodes::_l2f: { // >= Power7 - assert(VM_Version::has_fcfids(), "fcfid+frsp needs fixup code to avoid rounding incompatibility"); - __ fcfids(dst->as_float_reg(), src->as_double_reg()); // via mem - break; - } case Bytecodes::_f2d: { __ fmr_if_needed(dst->as_double_reg(), src->as_float_reg()); break; @@ -543,31 +566,49 @@ void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { } case Bytecodes::_d2i: case Bytecodes::_f2i: { + bool dst_in_memory = !VM_Version::has_mtfprd(); FloatRegister rsrc = (code == Bytecodes::_d2i) ? src->as_double_reg() : src->as_float_reg(); - Address addr = frame_map()->address_for_slot(dst->double_stack_ix()); + Address addr = dst_in_memory ? frame_map()->address_for_slot(dst->double_stack_ix()) : NULL; Label L; // Result must be 0 if value is NaN; test by comparing value to itself. __ fcmpu(CCR0, rsrc, rsrc); - __ li(R0, 0); // 0 in case of NAN - __ std(R0, addr.disp(), addr.base()); + if (dst_in_memory) { + __ li(R0, 0); // 0 in case of NAN + __ std(R0, addr.disp(), addr.base()); + } else { + __ li(dst->as_register(), 0); + } __ bso(CCR0, L); __ fctiwz(rsrc, rsrc); // USE_KILL - __ stfd(rsrc, addr.disp(), addr.base()); + if (dst_in_memory) { + __ stfd(rsrc, addr.disp(), addr.base()); + } else { + __ mffprd(dst->as_register(), rsrc); + } __ bind(L); break; } case Bytecodes::_d2l: case Bytecodes::_f2l: { + bool dst_in_memory = !VM_Version::has_mtfprd(); FloatRegister rsrc = (code == Bytecodes::_d2l) ? src->as_double_reg() : src->as_float_reg(); - Address addr = frame_map()->address_for_slot(dst->double_stack_ix()); + Address addr = dst_in_memory ? frame_map()->address_for_slot(dst->double_stack_ix()) : NULL; Label L; // Result must be 0 if value is NaN; test by comparing value to itself. __ fcmpu(CCR0, rsrc, rsrc); - __ li(R0, 0); // 0 in case of NAN - __ std(R0, addr.disp(), addr.base()); + if (dst_in_memory) { + __ li(R0, 0); // 0 in case of NAN + __ std(R0, addr.disp(), addr.base()); + } else { + __ li(dst->as_register_lo(), 0); + } __ bso(CCR0, L); __ fctidz(rsrc, rsrc); // USE_KILL - __ stfd(rsrc, addr.disp(), addr.base()); + if (dst_in_memory) { + __ stfd(rsrc, addr.disp(), addr.base()); + } else { + __ mffprd(dst->as_register_lo(), rsrc); + } __ bind(L); break; } @@ -3177,9 +3218,8 @@ void LIR_Assembler::emit_updatecrc32(LIR_OpUpdateCRC32* op) { assert_different_registers(val, crc, res); __ load_const_optimized(res, StubRoutines::crc_table_addr(), R0); - __ nand(crc, crc, crc); // ~crc - __ update_byte_crc32(crc, val, res); - __ nand(res, crc, crc); // ~crc + __ kernel_crc32_singleByteReg(crc, val, res, true); + __ mr(res, crc); } #undef __ diff --git a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp index 5bcd457e7e0..1a54ff4250d 100644 --- a/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/c1_LIRGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, SAP SE. 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 @@ -63,18 +63,6 @@ void LIRItem::load_nonconstant() { } -inline void load_int_as_long(LIR_List *ll, LIRItem &li, LIR_Opr dst) { - LIR_Opr r = li.value()->operand(); - if (r->is_register()) { - LIR_Opr dst_l = FrameMap::as_long_opr(dst->as_register()); - ll->convert(Bytecodes::_i2l, li.result(), dst_l); // Convert. - } else { - // Constants or memory get loaded with sign extend on this platform. - ll->move(li.result(), dst); - } -} - - //-------------------------------------------------------------- // LIRGenerator //-------------------------------------------------------------- @@ -883,81 +871,91 @@ void LIRGenerator::do_ArrayCopy(Intrinsic* x) { // _i2l, _i2f, _i2d, _l2i, _l2f, _l2d, _f2i, _f2l, _f2d, _d2i, _d2l, _d2f // _i2b, _i2c, _i2s void LIRGenerator::do_Convert(Convert* x) { - switch (x->op()) { + if (!VM_Version::has_mtfprd()) { + switch (x->op()) { - // int -> float: force spill - case Bytecodes::_l2f: { - if (!VM_Version::has_fcfids()) { // fcfids is >= Power7 only - // fcfid+frsp needs fixup code to avoid rounding incompatibility. - address entry = CAST_FROM_FN_PTR(address, SharedRuntime::l2f); - LIR_Opr result = call_runtime(x->value(), entry, x->type(), NULL); - set_result(x, result); + // int -> float: force spill + case Bytecodes::_l2f: { + if (!VM_Version::has_fcfids()) { // fcfids is >= Power7 only + // fcfid+frsp needs fixup code to avoid rounding incompatibility. + address entry = CAST_FROM_FN_PTR(address, SharedRuntime::l2f); + LIR_Opr result = call_runtime(x->value(), entry, x->type(), NULL); + set_result(x, result); + return; + } // else fallthru + } + case Bytecodes::_l2d: { + LIRItem value(x->value(), this); + LIR_Opr reg = rlock_result(x); + value.load_item(); + LIR_Opr tmp = force_to_spill(value.result(), T_DOUBLE); + __ convert(x->op(), tmp, reg); + return; + } + case Bytecodes::_i2f: + case Bytecodes::_i2d: { + LIRItem value(x->value(), this); + LIR_Opr reg = rlock_result(x); + value.load_item(); + // Convert i2l first. + LIR_Opr tmp1 = new_register(T_LONG); + __ convert(Bytecodes::_i2l, value.result(), tmp1); + LIR_Opr tmp2 = force_to_spill(tmp1, T_DOUBLE); + __ convert(x->op(), tmp2, reg); + return; + } + + // float -> int: result will be stored + case Bytecodes::_f2l: + case Bytecodes::_d2l: { + LIRItem value(x->value(), this); + LIR_Opr reg = rlock_result(x); + value.set_destroys_register(); // USE_KILL + value.load_item(); + set_vreg_flag(reg, must_start_in_memory); + __ convert(x->op(), value.result(), reg); + return; + } + case Bytecodes::_f2i: + case Bytecodes::_d2i: { + LIRItem value(x->value(), this); + LIR_Opr reg = rlock_result(x); + value.set_destroys_register(); // USE_KILL + value.load_item(); + // Convert l2i afterwards. + LIR_Opr tmp1 = new_register(T_LONG); + set_vreg_flag(tmp1, must_start_in_memory); + __ convert(x->op(), value.result(), tmp1); + __ convert(Bytecodes::_l2i, tmp1, reg); + return; + } + + // Within same category: just register conversions. + case Bytecodes::_i2b: + case Bytecodes::_i2c: + case Bytecodes::_i2s: + case Bytecodes::_i2l: + case Bytecodes::_l2i: + case Bytecodes::_f2d: + case Bytecodes::_d2f: break; - } // else fallthru - } - case Bytecodes::_l2d: { - LIRItem value(x->value(), this); - LIR_Opr reg = rlock_result(x); - value.load_item(); - LIR_Opr tmp = force_to_spill(value.result(), T_DOUBLE); - __ convert(x->op(), tmp, reg); - break; - } - case Bytecodes::_i2f: - case Bytecodes::_i2d: { - LIRItem value(x->value(), this); - LIR_Opr reg = rlock_result(x); - value.load_item(); - // Convert i2l first. - LIR_Opr tmp1 = new_register(T_LONG); - __ convert(Bytecodes::_i2l, value.result(), tmp1); - LIR_Opr tmp2 = force_to_spill(tmp1, T_DOUBLE); - __ convert(x->op(), tmp2, reg); - break; - } - // float -> int: result will be stored - case Bytecodes::_f2l: - case Bytecodes::_d2l: { - LIRItem value(x->value(), this); - LIR_Opr reg = rlock_result(x); - value.set_destroys_register(); // USE_KILL - value.load_item(); - set_vreg_flag(reg, must_start_in_memory); - __ convert(x->op(), value.result(), reg); - break; + default: ShouldNotReachHere(); } - case Bytecodes::_f2i: - case Bytecodes::_d2i: { - LIRItem value(x->value(), this); - LIR_Opr reg = rlock_result(x); - value.set_destroys_register(); // USE_KILL - value.load_item(); - // Convert l2i afterwards. - LIR_Opr tmp1 = new_register(T_LONG); - set_vreg_flag(tmp1, must_start_in_memory); - __ convert(x->op(), value.result(), tmp1); - __ convert(Bytecodes::_l2i, tmp1, reg); - break; - } - - // Within same category: just register conversions. - case Bytecodes::_i2b: - case Bytecodes::_i2c: - case Bytecodes::_i2s: - case Bytecodes::_i2l: - case Bytecodes::_l2i: - case Bytecodes::_f2d: - case Bytecodes::_d2f: { - LIRItem value(x->value(), this); - LIR_Opr reg = rlock_result(x); - value.load_item(); - __ convert(x->op(), value.result(), reg); - break; - } - - default: ShouldNotReachHere(); } + + // Register conversion. + LIRItem value(x->value(), this); + LIR_Opr reg = rlock_result(x); + value.load_item(); + switch (x->op()) { + case Bytecodes::_f2l: + case Bytecodes::_d2l: + case Bytecodes::_f2i: + case Bytecodes::_d2i: value.set_destroys_register(); break; // USE_KILL + default: break; + } + __ convert(x->op(), value.result(), reg); } @@ -1426,10 +1424,9 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { arg2 = cc->at(1), arg3 = cc->at(2); - // CCallingConventionRequiresIntsAsLongs crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32 stub doesn't care about high bits. __ leal(LIR_OprFact::address(a), arg2); - load_int_as_long(gen()->lir(), len, arg3); + len.load_item_force(arg3); // We skip int->long conversion here, , because CRC32 stub expects int. __ call_runtime_leaf(StubRoutines::updateBytesCRC32(), LIR_OprFact::illegalOpr, result_reg, cc->args()); __ move(result_reg, result); @@ -1441,6 +1438,76 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { } } +void LIRGenerator::do_update_CRC32C(Intrinsic* x) { + assert(UseCRC32CIntrinsics, "or should not be here"); + LIR_Opr result = rlock_result(x); + + switch (x->id()) { + case vmIntrinsics::_updateBytesCRC32C: + case vmIntrinsics::_updateDirectByteBufferCRC32C: { + bool is_updateBytes = (x->id() == vmIntrinsics::_updateBytesCRC32C); + + LIRItem crc(x->argument_at(0), this); + LIRItem buf(x->argument_at(1), this); + LIRItem off(x->argument_at(2), this); + LIRItem end(x->argument_at(3), this); + buf.load_item(); + off.load_nonconstant(); + end.load_nonconstant(); + + // len = end - off + LIR_Opr len = end.result(); + LIR_Opr tmpA = new_register(T_INT); + LIR_Opr tmpB = new_register(T_INT); + __ move(end.result(), tmpA); + __ move(off.result(), tmpB); + __ sub(tmpA, tmpB, tmpA); + len = tmpA; + + LIR_Opr index = off.result(); + int offset = is_updateBytes ? arrayOopDesc::base_offset_in_bytes(T_BYTE) : 0; + if (off.result()->is_constant()) { + index = LIR_OprFact::illegalOpr; + offset += off.result()->as_jint(); + } + LIR_Opr base_op = buf.result(); + LIR_Address* a = NULL; + + if (index->is_valid()) { + LIR_Opr tmp = new_register(T_LONG); + __ convert(Bytecodes::_i2l, index, tmp); + index = tmp; + __ add(index, LIR_OprFact::intptrConst(offset), index); + a = new LIR_Address(base_op, index, T_BYTE); + } else { + a = new LIR_Address(base_op, offset, T_BYTE); + } + + BasicTypeList signature(3); + signature.append(T_INT); + signature.append(T_ADDRESS); + signature.append(T_INT); + CallingConvention* cc = frame_map()->c_calling_convention(&signature); + const LIR_Opr result_reg = result_register_for(x->type()); + + LIR_Opr arg1 = cc->at(0), + arg2 = cc->at(1), + arg3 = cc->at(2); + + crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32C stub doesn't care about high bits. + __ leal(LIR_OprFact::address(a), arg2); + __ move(len, cc->at(2)); // We skip int->long conversion here, because CRC32C stub expects int. + + __ call_runtime_leaf(StubRoutines::updateBytesCRC32C(), LIR_OprFact::illegalOpr, result_reg, cc->args()); + __ move(result_reg, result); + break; + } + default: { + ShouldNotReachHere(); + } + } +} + void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { assert(x->number_of_arguments() == 3, "wrong type"); assert(UseFMA, "Needs FMA instructions support."); @@ -1467,7 +1534,3 @@ void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { fatal("vectorizedMismatch intrinsic is not implemented on this platform"); } - -void LIRGenerator::do_update_CRC32C(Intrinsic* x) { - Unimplemented(); -} diff --git a/hotspot/src/cpu/ppc/vm/c1_MacroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/c1_MacroAssembler_ppc.cpp index 377680a47eb..631b20b81a5 100644 --- a/hotspot/src/cpu/ppc/vm/c1_MacroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/c1_MacroAssembler_ppc.cpp @@ -36,6 +36,7 @@ #include "runtime/os.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/align.hpp" void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { @@ -340,7 +341,7 @@ void C1_MacroAssembler::allocate_array( // Check for negative or excessive length. size_t max_length = max_array_allocation_length >> log2_elt_size; if (UseTLAB) { - size_t max_tlab = align_size_up(ThreadLocalAllocBuffer::max_size() >> log2_elt_size, 64*K); + size_t max_tlab = align_up(ThreadLocalAllocBuffer::max_size() >> log2_elt_size, 64*K); if (max_tlab < max_length) { max_length = max_tlab; } } load_const_optimized(t1, max_length); diff --git a/hotspot/src/cpu/ppc/vm/c1_Runtime1_ppc.cpp b/hotspot/src/cpu/ppc/vm/c1_Runtime1_ppc.cpp index 3562a79825f..0c68f5a4c8b 100644 --- a/hotspot/src/cpu/ppc/vm/c1_Runtime1_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/c1_Runtime1_ppc.cpp @@ -36,6 +36,7 @@ #include "runtime/sharedRuntime.hpp" #include "runtime/signature.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/align.hpp" #include "utilities/macros.hpp" #include "vmreg_ppc.inline.hpp" #if INCLUDE_ALL_GCS @@ -251,7 +252,7 @@ void Runtime1::initialize_pd() { fpu_reg_save_offsets[i] = sp_offset; sp_offset += BytesPerWord; } - frame_size_in_bytes = align_size_up(sp_offset, frame::alignment_in_bytes); + frame_size_in_bytes = align_up(sp_offset, frame::alignment_in_bytes); } @@ -275,7 +276,7 @@ OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address targe static OopMapSet* generate_exception_throw_with_stack_parms(StubAssembler* sasm, address target, int stack_parms) { // Make a frame and preserve the caller's caller-save registers. - const int parm_size_in_bytes = align_size_up(stack_parms << LogBytesPerWord, frame::alignment_in_bytes); + const int parm_size_in_bytes = align_up(stack_parms << LogBytesPerWord, frame::alignment_in_bytes); const int padding = parm_size_in_bytes - (stack_parms << LogBytesPerWord); OopMap* oop_map = save_live_registers(sasm, true, noreg, parm_size_in_bytes); @@ -287,6 +288,7 @@ static OopMapSet* generate_exception_throw_with_stack_parms(StubAssembler* sasm, __ ld(R5_ARG3, frame_size_in_bytes + padding + 8, R1_SP); case 1: __ ld(R4_ARG2, frame_size_in_bytes + padding + 0, R1_SP); + case 0: call_offset = __ call_RT(noreg, noreg, target); break; default: Unimplemented(); break; @@ -325,7 +327,7 @@ OopMapSet* Runtime1::generate_stub_call(StubAssembler* sasm, Register result, ad static OopMapSet* stub_call_with_stack_parms(StubAssembler* sasm, Register result, address target, int stack_parms, bool do_return = true) { // Make a frame and preserve the caller's caller-save registers. - const int parm_size_in_bytes = align_size_up(stack_parms << LogBytesPerWord, frame::alignment_in_bytes); + const int parm_size_in_bytes = align_up(stack_parms << LogBytesPerWord, frame::alignment_in_bytes); const int padding = parm_size_in_bytes - (stack_parms << LogBytesPerWord); OopMap* oop_map = save_live_registers(sasm, true, noreg, parm_size_in_bytes); @@ -337,6 +339,7 @@ static OopMapSet* stub_call_with_stack_parms(StubAssembler* sasm, Register resul __ ld(R5_ARG3, frame_size_in_bytes + padding + 8, R1_SP); case 1: __ ld(R4_ARG2, frame_size_in_bytes + padding + 0, R1_SP); + case 0: call_offset = __ call_RT(result, noreg, target); break; default: Unimplemented(); break; diff --git a/hotspot/src/cpu/ppc/vm/frame_ppc.cpp b/hotspot/src/cpu/ppc/vm/frame_ppc.cpp index b6a538681f6..7437d33fc5c 100644 --- a/hotspot/src/cpu/ppc/vm/frame_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/frame_ppc.cpp @@ -244,4 +244,6 @@ intptr_t *frame::initial_deoptimization_info() { frame::frame(void* sp, void* fp, void* pc) : _sp((intptr_t*)sp), _unextended_sp((intptr_t*)sp) { find_codeblob_and_set_pc_and_deopt_state((address)pc); // also sets _fp and adjusts _unextended_sp } + +void frame::pd_ps() {} #endif diff --git a/hotspot/src/cpu/ppc/vm/frame_ppc.hpp b/hotspot/src/cpu/ppc/vm/frame_ppc.hpp index ccec598c1ad..6023aa85066 100644 --- a/hotspot/src/cpu/ppc/vm/frame_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/frame_ppc.hpp @@ -82,13 +82,7 @@ public: // C frame layout - - enum { - // stack alignment - alignment_in_bytes = 16, - // log_2(16*8 bits) = 7. - log_2_of_alignment_in_bits = 7 - }; + static const int alignment_in_bytes = 16; // ABI_MINFRAME: struct abi_minframe { diff --git a/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp index d22f5b564e8..15c4bce9dc4 100644 --- a/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp +++ b/hotspot/src/cpu/ppc/vm/frame_ppc.inline.hpp @@ -28,6 +28,7 @@ #include "code/codeCache.hpp" #include "code/vmreg.inline.hpp" +#include "utilities/align.hpp" // Inline functions for ppc64 frames: @@ -193,7 +194,7 @@ inline intptr_t* frame::interpreter_frame_tos_at(jint offset) const { inline int frame::interpreter_frame_monitor_size() { // Number of stack slots for a monitor. - return round_to(BasicObjectLock::size(), // number of stack slots + return align_up(BasicObjectLock::size(), // number of stack slots WordsPerLong); // number of stack slots for a Java long } diff --git a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp index bf4ca17df09..0bc041e9188 100644 --- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 SAP SE. 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 @@ -164,7 +164,7 @@ define_pd_global(intx, InitArrayShortSize, 9*BytesPerLong); product(bool, ZapMemory, false, "Write 0x0101... to empty memory." \ " Use this to ease debugging.") \ \ - /* Use Restricted Transactional Memory for lock eliding */ \ + /* Use Restricted Transactional Memory for lock elision */ \ product(bool, UseRTMLocking, false, \ "Enable RTM lock eliding for inflated locks in compiled code") \ \ @@ -174,24 +174,31 @@ define_pd_global(intx, InitArrayShortSize, 9*BytesPerLong); product(bool, UseRTMDeopt, false, \ "Perform deopt and recompilation based on RTM abort ratio") \ \ - product(uintx, RTMRetryCount, 5, \ + product(int, RTMRetryCount, 5, \ "Number of RTM retries on lock abort or busy") \ + range(0, max_jint) \ \ - experimental(intx, RTMSpinLoopCount, 100, \ + experimental(int, RTMSpinLoopCount, 100, \ "Spin count for lock to become free before RTM retry") \ + range(0, 32767) /* immediate operand limit on ppc */ \ \ - experimental(intx, RTMAbortThreshold, 1000, \ + experimental(int, RTMAbortThreshold, 1000, \ "Calculate abort ratio after this number of aborts") \ + range(0, max_jint) \ \ - experimental(intx, RTMLockingThreshold, 10000, \ + experimental(int, RTMLockingThreshold, 10000, \ "Lock count at which to do RTM lock eliding without " \ "abort ratio calculation") \ + range(0, max_jint) \ \ - experimental(intx, RTMAbortRatio, 50, \ + experimental(int, RTMAbortRatio, 50, \ "Lock abort ratio at which to stop use RTM lock eliding") \ + range(0, 100) /* natural range */ \ \ - experimental(intx, RTMTotalCountIncrRate, 64, \ + experimental(int, RTMTotalCountIncrRate, 64, \ "Increment total RTM attempted lock count once every n times") \ + range(1, 32767) /* immediate operand limit on ppc */ \ + constraint(RTMTotalCountIncrRateConstraintFunc,AfterErgo) \ \ experimental(intx, RTMLockingCalculationDelay, 0, \ "Number of milliseconds to wait before start calculating aborts " \ diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp index d2085ea4e78..b49f8bb424f 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 SAP SE. 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 @@ -45,8 +45,8 @@ class InterpreterMacroAssembler: public MacroAssembler { #define thread_(field_name) in_bytes(JavaThread::field_name ## _offset()), R16_thread #define method_(field_name) in_bytes(Method::field_name ## _offset()), R19_method - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); + virtual void check_and_handle_popframe(Register scratch_reg); + virtual void check_and_handle_earlyret(Register scratch_reg); // Base routine for all dispatches. void dispatch_base(TosState state, address* table); @@ -79,6 +79,9 @@ class InterpreterMacroAssembler: public MacroAssembler { // Load object from cpool->resolved_references(index). void load_resolved_reference_at_index(Register result, Register index, Label *is_null = NULL); + // load cpool->resolved_klass_at(index) + void load_resolved_klass_at_offset(Register Rcpool, Register Roffset, Register Rklass); + void load_receiver(Register Rparam_count, Register Rrecv_dst); // helpers for expression stack @@ -96,8 +99,8 @@ class InterpreterMacroAssembler: public MacroAssembler { void push_2ptrs(Register first, Register second); - void push_l_pop_d(Register l = R17_tos, FloatRegister d = F15_ftos); - void push_d_pop_l(FloatRegister d = F15_ftos, Register l = R17_tos); + void move_l_to_d(Register l = R17_tos, FloatRegister d = F15_ftos); + void move_d_to_l(FloatRegister d = F15_ftos, Register l = R17_tos); void pop (TosState state); // transition vtos -> state void push(TosState state); // transition state -> vtos diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp index 95234115319..1715ddc3fa0 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 SAP SE. 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 @@ -284,14 +284,22 @@ void InterpreterMacroAssembler::push_2ptrs(Register first, Register second) { addi(R15_esp, R15_esp, - 2 * Interpreter::stackElementSize ); } -void InterpreterMacroAssembler::push_l_pop_d(Register l, FloatRegister d) { - std(l, 0, R15_esp); - lfd(d, 0, R15_esp); +void InterpreterMacroAssembler::move_l_to_d(Register l, FloatRegister d) { + if (VM_Version::has_mtfprd()) { + mtfprd(d, l); + } else { + std(l, 0, R15_esp); + lfd(d, 0, R15_esp); + } } -void InterpreterMacroAssembler::push_d_pop_l(FloatRegister d, Register l) { - stfd(d, 0, R15_esp); - ld(l, 0, R15_esp); +void InterpreterMacroAssembler::move_d_to_l(FloatRegister d, Register l) { + if (VM_Version::has_mtfprd()) { + mffprd(l, d); + } else { + stfd(d, 0, R15_esp); + ld(l, 0, R15_esp); + } } void InterpreterMacroAssembler::push(TosState state) { @@ -454,7 +462,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result Register tmp = index; // reuse sldi(tmp, index, LogBytesPerHeapOop); // Load pointer for resolved_references[] objArray. - ld(result, ConstantPool::resolved_references_offset_in_bytes(), result); + ld(result, ConstantPool::cache_offset_in_bytes(), result); + ld(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result); // JNIHandles::resolve(result) ld(result, 0, result); #ifdef ASSERT @@ -471,6 +480,25 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result, is_null); } +// load cpool->resolved_klass_at(index) +void InterpreterMacroAssembler::load_resolved_klass_at_offset(Register Rcpool, Register Roffset, Register Rklass) { + // int value = *(Rcpool->int_at_addr(which)); + // int resolved_klass_index = extract_low_short_from_int(value); + add(Roffset, Rcpool, Roffset); +#if defined(VM_LITTLE_ENDIAN) + lhz(Roffset, sizeof(ConstantPool), Roffset); // Roffset = resolved_klass_index +#else + lhz(Roffset, sizeof(ConstantPool) + 2, Roffset); // Roffset = resolved_klass_index +#endif + + ld(Rklass, ConstantPool::resolved_klasses_offset_in_bytes(), Rcpool); // Rklass = Rcpool->_resolved_klasses + + sldi(Roffset, Roffset, LogBytesPerWord); + addi(Roffset, Roffset, Array::base_offset_in_bytes()); + isync(); // Order load of instance Klass wrt. tags. + ldx(Rklass, Rklass, Roffset); +} + // Generate a subtype check: branch to ok_is_subtype if sub_klass is // a subtype of super_klass. Blows registers Rsub_klass, tmp1, tmp2. void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, Register Rsuper_klass, Register Rtmp1, diff --git a/hotspot/src/cpu/ppc/vm/interpreterRT_ppc.hpp b/hotspot/src/cpu/ppc/vm/interpreterRT_ppc.hpp index d71781cbc83..a3e8fa632bf 100644 --- a/hotspot/src/cpu/ppc/vm/interpreterRT_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/interpreterRT_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2014 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -45,7 +45,7 @@ class SignatureHandlerGenerator: public NativeSignatureIterator { public: // Creation - SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) { + SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) { _masm = new MacroAssembler(buffer); _num_used_fp_arg_regs = 0; } diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index 6eb27c78f17..fa4b2fe2427 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2017 SAP SE. All rights reserved. + * Copyright (c) 2012, 2017, SAP SE. 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 @@ -2498,14 +2498,20 @@ void MacroAssembler::rtm_abort_ratio_calculation(Register rtm_counters_Reg, // All transactions = total_count * RTMTotalCountIncrRate // Set no_rtm bit if (Aborted transactions >= All transactions * RTMAbortRatio) ld(R0, RTMLockingCounters::abort_count_offset(), rtm_counters_Reg); - cmpdi(CCR0, R0, RTMAbortThreshold); - blt(CCR0, L_check_always_rtm2); + if (is_simm(RTMAbortThreshold, 16)) { // cmpdi can handle 16bit immediate only. + cmpdi(CCR0, R0, RTMAbortThreshold); + blt(CCR0, L_check_always_rtm2); // reload of rtm_counters_Reg not necessary + } else { + load_const_optimized(rtm_counters_Reg, RTMAbortThreshold); + cmpd(CCR0, R0, rtm_counters_Reg); + blt(CCR0, L_check_always_rtm1); // reload of rtm_counters_Reg required + } mulli(R0, R0, 100); const Register tmpReg = rtm_counters_Reg; ld(tmpReg, RTMLockingCounters::total_count_offset(), rtm_counters_Reg); - mulli(tmpReg, tmpReg, RTMTotalCountIncrRate); - mulli(tmpReg, tmpReg, RTMAbortRatio); + mulli(tmpReg, tmpReg, RTMTotalCountIncrRate); // allowable range: int16 + mulli(tmpReg, tmpReg, RTMAbortRatio); // allowable range: int16 cmpd(CCR0, R0, tmpReg); blt(CCR0, L_check_always_rtm1); // jump to reload if (method_data != NULL) { @@ -2521,7 +2527,13 @@ void MacroAssembler::rtm_abort_ratio_calculation(Register rtm_counters_Reg, load_const_optimized(rtm_counters_Reg, (address)rtm_counters, R0); // reload bind(L_check_always_rtm2); ld(tmpReg, RTMLockingCounters::total_count_offset(), rtm_counters_Reg); - cmpdi(CCR0, tmpReg, RTMLockingThreshold / RTMTotalCountIncrRate); + int64_t thresholdValue = RTMLockingThreshold / RTMTotalCountIncrRate; + if (is_simm(thresholdValue, 16)) { // cmpdi can handle 16bit immediate only. + cmpdi(CCR0, tmpReg, thresholdValue); + } else { + load_const_optimized(R0, thresholdValue); + cmpd(CCR0, tmpReg, R0); + } blt(CCR0, L_done); if (method_data != NULL) { // Set rtm_state to "always rtm" in MDO. @@ -2620,7 +2632,7 @@ void MacroAssembler::rtm_stack_locking(ConditionRegister flag, if (PrintPreciseRTMLockingStatistics || profile_rtm) { Label L_noincrement; if (RTMTotalCountIncrRate > 1) { - branch_on_random_using_tb(tmp, (int)RTMTotalCountIncrRate, L_noincrement); + branch_on_random_using_tb(tmp, RTMTotalCountIncrRate, L_noincrement); } assert(stack_rtm_counters != NULL, "should not be NULL when profiling RTM"); load_const_optimized(tmp, (address)stack_rtm_counters->total_count_addr(), R0); @@ -2687,7 +2699,7 @@ void MacroAssembler::rtm_inflated_locking(ConditionRegister flag, if (PrintPreciseRTMLockingStatistics || profile_rtm) { Label L_noincrement; if (RTMTotalCountIncrRate > 1) { - branch_on_random_using_tb(R0, (int)RTMTotalCountIncrRate, L_noincrement); + branch_on_random_using_tb(R0, RTMTotalCountIncrRate, L_noincrement); } assert(rtm_counters != NULL, "should not be NULL when profiling RTM"); load_const(R0, (address)rtm_counters->total_count_addr(), tmpReg); @@ -4120,7 +4132,7 @@ void MacroAssembler::update_byte_crc32(Register crc, Register val, Register tabl * @param table register pointing to CRC table */ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, - Register data, bool loopAlignment, bool invertCRC) { + Register data, bool loopAlignment) { assert_different_registers(crc, buf, len, table, data); Label L_mainLoop, L_done; @@ -4131,10 +4143,6 @@ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register clrldi_(len, len, 32); // Enforce 32 bit. Anything to do? beq(CCR0, L_done); - if (invertCRC) { - nand(crc, crc, crc); // ~c - } - mtctr(len); align(mainLoop_alignment); BIND(L_mainLoop); @@ -4143,10 +4151,6 @@ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register update_byte_crc32(crc, data, table); bdnz(L_mainLoop); // Iterate. - if (invertCRC) { - nand(crc, crc, crc); // ~c - } - bind(L_done); } @@ -4203,7 +4207,8 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab */ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len, Register table, Register t0, Register t1, Register t2, Register t3, - Register tc0, Register tc1, Register tc2, Register tc3) { + Register tc0, Register tc1, Register tc2, Register tc3, + bool invertCRC) { assert_different_registers(crc, buf, len, table); Label L_mainLoop, L_tail; @@ -4217,14 +4222,16 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len const int complexThreshold = 2*mainLoop_stepping; // Don't test for len <= 0 here. This pathological case should not occur anyway. - // Optimizing for it by adding a test and a branch seems to be a waste of CPU cycles. - // The situation itself is detected and handled correctly by the conditional branches - // following aghi(len, -stepping) and aghi(len, +stepping). + // Optimizing for it by adding a test and a branch seems to be a waste of CPU cycles + // for all well-behaved cases. The situation itself is detected and handled correctly + // within update_byteLoop_crc32. assert(tailLoop_stepping == 1, "check tailLoop_stepping!"); BLOCK_COMMENT("kernel_crc32_2word {"); - nand(crc, crc, crc); // ~c + if (invertCRC) { + nand(crc, crc, crc); // 1s complement of crc + } // Check for short (=mainLoop_stepping is guaranteed). } - update_byteLoop_crc32(crc, buf, tmp2, table, data, false, false); + update_byteLoop_crc32(crc, buf, tmp2, table, data, false); } srdi(tmp2, len, log_stepping); // #iterations for mainLoop @@ -4281,9 +4288,11 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len // Process last few (=mainLoop_stepping is guaranteed). } - update_byteLoop_crc32(crc, buf, tmp2, table, data, false, false); + update_byteLoop_crc32(crc, buf, tmp2, table, data, false); } srdi(tmp2, len, log_stepping); // #iterations for mainLoop @@ -4374,9 +4386,11 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len // Process last few (klass()->klass_part()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no releationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - // There are more general problems with CDS on ppc, so I can not - // really test this. But having this instead of Unimplementd() allows - // us to pass TestOptionsWithRanges.java. - __ unimplemented(); -} - diff --git a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp index a4bb111d9e0..ff0fcb85dcb 100644 --- a/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/methodHandles_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 SAP SE. 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 @@ -29,6 +29,7 @@ #include "interpreter/interpreter.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" +#include "prims/jvm.h" #include "prims/methodHandles.hpp" #define __ _masm-> @@ -71,7 +72,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register temp_reg, Register temp2_reg, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); Label L_ok, L_bad; BLOCK_COMMENT("verify_klass {"); __ verify_oop(obj_reg); @@ -174,8 +175,9 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, __ verify_oop(method_temp); __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp, temp2); __ verify_oop(method_temp); - // The following assumes that a Method* is normally compressed in the vmtarget field: - __ ld(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), method_temp); + __ load_heap_oop_not_null(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), method_temp); + __ verify_oop(method_temp); + __ ld(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), method_temp); if (VerifyMethodHandles && !for_compiler_entry) { // Make sure recv is already on stack. @@ -361,14 +363,16 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp2); } - __ ld(R19_method, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), member_reg); + __ load_heap_oop(R19_method, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), member_reg); + __ ld(R19_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), R19_method); break; case vmIntrinsics::_linkToStatic: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp2); } - __ ld(R19_method, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()), member_reg); + __ load_heap_oop(R19_method, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), member_reg); + __ ld(R19_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()), R19_method); break; case vmIntrinsics::_linkToVirtual: diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index f9534b65bff..de0d6088460 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -1,6 +1,6 @@ // -// Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. -// Copyright (c) 2012, 2016 SAP SE. All rights reserved. +// Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2012, 2017 SAP SE. 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 @@ -2053,12 +2053,12 @@ const int Matcher::vector_width_in_bytes(BasicType bt) { } // Vector ideal reg. -const int Matcher::vector_ideal_reg(int size) { +const uint Matcher::vector_ideal_reg(int size) { assert(MaxVectorSize == 8 && size == 8, ""); return Op_RegL; } -const int Matcher::vector_shift_count_ideal_reg(int size) { +const uint Matcher::vector_shift_count_ideal_reg(int size) { fatal("vector shift is not supported"); return Node::NotAMachineReg; } @@ -3079,6 +3079,17 @@ encode %{ __ bind(done); %} + enc_class enc_cmove_bso_reg(iRegLdst dst, flagsRegSrc crx, regD src) %{ + // TODO: PPC port $archOpcode(ppc64Opcode_cmove); + + MacroAssembler _masm(&cbuf); + Label done; + __ bso($crx$$CondRegister, done); + __ mffprd($dst$$Register, $src$$FloatRegister); + // TODO PPC port __ endgroup_if_needed(_size == 12); + __ bind(done); + %} + enc_class enc_bc(flagsRegSrc crx, cmpOp cmp, Label lbl) %{ // TODO: PPC port $archOpcode(ppc64Opcode_bc); @@ -5842,6 +5853,16 @@ instruct loadConN_lo(iRegNdst dst, iRegNsrc src1, immN src2) %{ ins_pipe(pipe_class_default); %} +instruct rldicl(iRegLdst dst, iRegLsrc src, immI16 shift, immI16 mask_begin) %{ + effect(DEF dst, USE src, USE shift, USE mask_begin); + + size(4); + ins_encode %{ + __ rldicl($dst$$Register, $src$$Register, $shift$$constant, $mask_begin$$constant); + %} + ins_pipe(pipe_class_default); +%} + // Needed to postalloc expand loadConN: ConN is loaded as ConI // leaving the upper 32 bits with sign-extension bits. // This clears these bits: dst = src & 0xFFFFFFFF. @@ -9306,6 +9327,44 @@ instruct shrP_convP2X_reg_imm6(iRegLdst dst, iRegP_N2P src1, uimmI6 src2) %{ ins_pipe(pipe_class_default); %} +// Bitfield Extract: URShiftI + AndI +instruct andI_urShiftI_regI_immI_immIpow2minus1(iRegIdst dst, iRegIsrc src1, immI src2, immIpow2minus1 src3) %{ + match(Set dst (AndI (URShiftI src1 src2) src3)); + + format %{ "EXTRDI $dst, $src1, shift=$src2, mask=$src3 \t// int bitfield extract" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); + int rshift = ($src2$$constant) & 0x1f; + int length = log2_long(((jlong) $src3$$constant) + 1); + if (rshift + length > 32) { + // if necessary, adjust mask to omit rotated bits. + length = 32 - rshift; + } + __ extrdi($dst$$Register, $src1$$Register, length, 64 - (rshift + length)); + %} + ins_pipe(pipe_class_default); +%} + +// Bitfield Extract: URShiftL + AndL +instruct andL_urShiftL_regL_immI_immLpow2minus1(iRegLdst dst, iRegLsrc src1, immI src2, immLpow2minus1 src3) %{ + match(Set dst (AndL (URShiftL src1 src2) src3)); + + format %{ "EXTRDI $dst, $src1, shift=$src2, mask=$src3 \t// long bitfield extract" %} + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); + int rshift = ($src2$$constant) & 0x3f; + int length = log2_long(((jlong) $src3$$constant) + 1); + if (rshift + length > 64) { + // if necessary, adjust mask to omit rotated bits. + length = 64 - rshift; + } + __ extrdi($dst$$Register, $src1$$Register, length, 64 - (rshift + length)); + %} + ins_pipe(pipe_class_default); +%} + instruct sxtI_reg(iRegIdst dst, iRegIsrc src) %{ match(Set dst (ConvL2I (ConvI2L src))); @@ -10078,9 +10137,36 @@ instruct andcL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ // float intBitsToFloat(int bits) // // Notes on the implementation on ppc64: -// We only provide rules which move between a register and a stack-location, -// because we always have to go through memory when moving between a float -// register and an integer register. +// For Power7 and earlier, the rules are limited to those which move between a +// register and a stack-location, because we always have to go through memory +// when moving between a float register and an integer register. +// This restriction is removed in Power8 with the introduction of the mtfprd +// and mffprd instructions. + +instruct moveL2D_reg(regD dst, iRegLsrc src) %{ + match(Set dst (MoveL2D src)); + predicate(VM_Version::has_mtfprd()); + + format %{ "MTFPRD $dst, $src" %} + size(4); + ins_encode %{ + __ mtfprd($dst$$FloatRegister, $src$$Register); + %} + ins_pipe(pipe_class_default); +%} + +instruct moveI2D_reg(regD dst, iRegIsrc src) %{ + // no match-rule, false predicate + effect(DEF dst, USE src); + predicate(false); + + format %{ "MTFPRWA $dst, $src" %} + size(4); + ins_encode %{ + __ mtfprwa($dst$$FloatRegister, $src$$Register); + %} + ins_pipe(pipe_class_default); +%} //---------- Chain stack slots between similar types -------- @@ -10519,6 +10605,16 @@ instruct convB2I_reg(iRegIdst dst, iRegIsrc src, immI_24 amount) %{ ins_pipe(pipe_class_default); %} +instruct extsh(iRegIdst dst, iRegIsrc src) %{ + effect(DEF dst, USE src); + + size(4); + ins_encode %{ + __ extsh($dst$$Register, $src$$Register); + %} + ins_pipe(pipe_class_default); +%} + // LShiftI 16 + RShiftI 16 converts short to int. instruct convS2I_reg(iRegIdst dst, iRegIsrc src, immI_16 amount) %{ match(Set dst (RShiftI (LShiftI src amount) amount)); @@ -10583,6 +10679,20 @@ instruct cmovI_bso_stackSlotL(iRegIdst dst, flagsRegSrc crx, stackSlotL src) %{ ins_pipe(pipe_class_default); %} +instruct cmovI_bso_reg(iRegIdst dst, flagsRegSrc crx, regD src) %{ + // no match-rule, false predicate + effect(DEF dst, USE crx, USE src); + predicate(false); + + ins_variable_size_depending_on_alignment(true); + + format %{ "cmovI $crx, $dst, $src" %} + // Worst case is branch + move + stop, no stop without scheduler. + size(false /* TODO: PPC PORT(InsertEndGroupPPC64 && Compile::current()->do_hb_scheduling())*/ ? 12 : 8); + ins_encode( enc_cmove_bso_reg(dst, crx, src) ); + ins_pipe(pipe_class_default); +%} + instruct cmovI_bso_stackSlotL_conLvalue0_Ex(iRegIdst dst, flagsRegSrc crx, stackSlotL mem) %{ // no match-rule, false predicate effect(DEF dst, USE crx, USE mem); @@ -10637,9 +10747,64 @@ instruct cmovI_bso_stackSlotL_conLvalue0_Ex(iRegIdst dst, flagsRegSrc crx, stack %} %} +instruct cmovI_bso_reg_conLvalue0_Ex(iRegIdst dst, flagsRegSrc crx, regD src) %{ + // no match-rule, false predicate + effect(DEF dst, USE crx, USE src); + predicate(false); + + format %{ "CmovI $dst, $crx, $src \t// postalloc expanded" %} + postalloc_expand %{ + // + // replaces + // + // region dst crx src + // \ | | / + // dst=cmovI_bso_reg_conLvalue0 + // + // with + // + // region dst + // \ / + // dst=loadConI16(0) + // | + // ^ region dst crx src + // | \ | | / + // dst=cmovI_bso_reg + // + + // Create new nodes. + MachNode *m1 = new loadConI16Node(); + MachNode *m2 = new cmovI_bso_regNode(); + + // inputs for new nodes + m1->add_req(n_region); + m2->add_req(n_region, n_crx, n_src); + + // precedences for new nodes + m2->add_prec(m1); + + // operands for new nodes + m1->_opnds[0] = op_dst; + m1->_opnds[1] = new immI16Oper(0); + + m2->_opnds[0] = op_dst; + m2->_opnds[1] = op_crx; + m2->_opnds[2] = op_src; + + // registers for new nodes + ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst + ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst + + // Insert new nodes. + nodes->push(m1); + nodes->push(m2); + %} +%} + // Double to Int conversion, NaN is mapped to 0. instruct convD2I_reg_ExEx(iRegIdst dst, regD src) %{ match(Set dst (ConvD2I src)); + predicate(!VM_Version::has_mtfprd()); ins_cost(DEFAULT_COST); expand %{ @@ -10653,6 +10818,21 @@ instruct convD2I_reg_ExEx(iRegIdst dst, regD src) %{ %} %} +// Double to Int conversion, NaN is mapped to 0. Special version for Power8. +instruct convD2I_reg_mffprd_ExEx(iRegIdst dst, regD src) %{ + match(Set dst (ConvD2I src)); + predicate(VM_Version::has_mtfprd()); + ins_cost(DEFAULT_COST); + + expand %{ + regD tmpD; + flagsReg crx; + cmpDUnordered_reg_reg(crx, src, src); // Check whether src is NaN. + convD2IRaw_regD(tmpD, src); // Convert float to int (speculated). + cmovI_bso_reg_conLvalue0_Ex(dst, crx, tmpD); // Cmove based on NaN check. + %} +%} + instruct convF2IRaw_regF(regF dst, regF src) %{ // no match-rule, false predicate effect(DEF dst, USE src); @@ -10670,6 +10850,7 @@ instruct convF2IRaw_regF(regF dst, regF src) %{ // Float to Int conversion, NaN is mapped to 0. instruct convF2I_regF_ExEx(iRegIdst dst, regF src) %{ match(Set dst (ConvF2I src)); + predicate(!VM_Version::has_mtfprd()); ins_cost(DEFAULT_COST); expand %{ @@ -10683,6 +10864,21 @@ instruct convF2I_regF_ExEx(iRegIdst dst, regF src) %{ %} %} +// Float to Int conversion, NaN is mapped to 0. Special version for Power8. +instruct convF2I_regF_mffprd_ExEx(iRegIdst dst, regF src) %{ + match(Set dst (ConvF2I src)); + predicate(VM_Version::has_mtfprd()); + ins_cost(DEFAULT_COST); + + expand %{ + regF tmpF; + flagsReg crx; + cmpFUnordered_reg_reg(crx, src, src); // Check whether src is NaN. + convF2IRaw_regF(tmpF, src); // Convert float to int (speculated). + cmovI_bso_reg_conLvalue0_Ex(dst, crx, tmpF); // Cmove based on NaN check. + %} +%} + // Convert to Long instruct convI2L_reg(iRegLdst dst, iRegIsrc src) %{ @@ -10752,6 +10948,20 @@ instruct cmovL_bso_stackSlotL(iRegLdst dst, flagsRegSrc crx, stackSlotL src) %{ ins_pipe(pipe_class_default); %} +instruct cmovL_bso_reg(iRegLdst dst, flagsRegSrc crx, regD src) %{ + // no match-rule, false predicate + effect(DEF dst, USE crx, USE src); + predicate(false); + + ins_variable_size_depending_on_alignment(true); + + format %{ "cmovL $crx, $dst, $src" %} + // Worst case is branch + move + stop, no stop without scheduler. + size(false /* TODO: PPC PORT Compile::current()->do_hb_scheduling()*/ ? 12 : 8); + ins_encode( enc_cmove_bso_reg(dst, crx, src) ); + ins_pipe(pipe_class_default); +%} + instruct cmovL_bso_stackSlotL_conLvalue0_Ex(iRegLdst dst, flagsRegSrc crx, stackSlotL mem) %{ // no match-rule, false predicate effect(DEF dst, USE crx, USE mem); @@ -10803,9 +11013,61 @@ instruct cmovL_bso_stackSlotL_conLvalue0_Ex(iRegLdst dst, flagsRegSrc crx, stack %} %} +instruct cmovL_bso_reg_conLvalue0_Ex(iRegLdst dst, flagsRegSrc crx, regD src) %{ + // no match-rule, false predicate + effect(DEF dst, USE crx, USE src); + predicate(false); + + format %{ "CmovL $dst, $crx, $src \t// postalloc expanded" %} + postalloc_expand %{ + // + // replaces + // + // region dst crx src + // \ | | / + // dst=cmovL_bso_reg_conLvalue0 + // + // with + // + // region dst + // \ / + // dst=loadConL16(0) + // | + // ^ region dst crx src + // | \ | | / + // dst=cmovL_bso_reg + // + + // Create new nodes. + MachNode *m1 = new loadConL16Node(); + MachNode *m2 = new cmovL_bso_regNode(); + + // inputs for new nodes + m1->add_req(n_region); + m2->add_req(n_region, n_crx, n_src); + m2->add_prec(m1); + + // operands for new nodes + m1->_opnds[0] = op_dst; + m1->_opnds[1] = new immL16Oper(0); + m2->_opnds[0] = op_dst; + m2->_opnds[1] = op_crx; + m2->_opnds[2] = op_src; + + // registers for new nodes + ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst + ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst + + // Insert new nodes. + nodes->push(m1); + nodes->push(m2); + %} +%} + // Float to Long conversion, NaN is mapped to 0. instruct convF2L_reg_ExEx(iRegLdst dst, regF src) %{ match(Set dst (ConvF2L src)); + predicate(!VM_Version::has_mtfprd()); ins_cost(DEFAULT_COST); expand %{ @@ -10819,6 +11081,21 @@ instruct convF2L_reg_ExEx(iRegLdst dst, regF src) %{ %} %} +// Float to Long conversion, NaN is mapped to 0. Special version for Power8. +instruct convF2L_reg_mffprd_ExEx(iRegLdst dst, regF src) %{ + match(Set dst (ConvF2L src)); + predicate(VM_Version::has_mtfprd()); + ins_cost(DEFAULT_COST); + + expand %{ + regF tmpF; + flagsReg crx; + cmpFUnordered_reg_reg(crx, src, src); // Check whether src is NaN. + convF2LRaw_regF(tmpF, src); // Convert float to long (speculated). + cmovL_bso_reg_conLvalue0_Ex(dst, crx, tmpF); // Cmove based on NaN check. + %} +%} + instruct convD2LRaw_regD(regD dst, regD src) %{ // no match-rule, false predicate effect(DEF dst, USE src); @@ -10836,6 +11113,7 @@ instruct convD2LRaw_regD(regD dst, regD src) %{ // Double to Long conversion, NaN is mapped to 0. instruct convD2L_reg_ExEx(iRegLdst dst, regD src) %{ match(Set dst (ConvD2L src)); + predicate(!VM_Version::has_mtfprd()); ins_cost(DEFAULT_COST); expand %{ @@ -10849,6 +11127,21 @@ instruct convD2L_reg_ExEx(iRegLdst dst, regD src) %{ %} %} +// Double to Long conversion, NaN is mapped to 0. Special version for Power8. +instruct convD2L_reg_mffprd_ExEx(iRegLdst dst, regD src) %{ + match(Set dst (ConvD2L src)); + predicate(VM_Version::has_mtfprd()); + ins_cost(DEFAULT_COST); + + expand %{ + regD tmpD; + flagsReg crx; + cmpDUnordered_reg_reg(crx, src, src); // Check whether src is NaN. + convD2LRaw_regD(tmpD, src); // Convert float to long (speculated). + cmovL_bso_reg_conLvalue0_Ex(dst, crx, tmpD); // Cmove based on NaN check. + %} +%} + // Convert to Float // Placed here as needed in expand. @@ -10914,7 +11207,7 @@ instruct convL2FRaw_regF(regF dst, regD src) %{ // Integer to Float conversion. Special version for Power7. instruct convI2F_ireg_fcfids_Ex(regF dst, iRegIsrc src) %{ match(Set dst (ConvI2F src)); - predicate(VM_Version::has_fcfids()); + predicate(VM_Version::has_fcfids() && !VM_Version::has_mtfprd()); ins_cost(DEFAULT_COST); expand %{ @@ -10928,10 +11221,23 @@ instruct convI2F_ireg_fcfids_Ex(regF dst, iRegIsrc src) %{ %} %} +// Integer to Float conversion. Special version for Power8. +instruct convI2F_ireg_mtfprd_Ex(regF dst, iRegIsrc src) %{ + match(Set dst (ConvI2F src)); + predicate(VM_Version::has_fcfids() && VM_Version::has_mtfprd()); + ins_cost(DEFAULT_COST); + + expand %{ + regD tmpD; + moveI2D_reg(tmpD, src); + convL2FRaw_regF(dst, tmpD); // Convert to float. + %} +%} + // L2F to avoid runtime call. instruct convL2F_ireg_fcfids_Ex(regF dst, iRegLsrc src) %{ match(Set dst (ConvL2F src)); - predicate(VM_Version::has_fcfids()); + predicate(VM_Version::has_fcfids() && !VM_Version::has_mtfprd()); ins_cost(DEFAULT_COST); expand %{ @@ -10943,6 +11249,19 @@ instruct convL2F_ireg_fcfids_Ex(regF dst, iRegLsrc src) %{ %} %} +// L2F to avoid runtime call. Special version for Power8. +instruct convL2F_ireg_mtfprd_Ex(regF dst, iRegLsrc src) %{ + match(Set dst (ConvL2F src)); + predicate(VM_Version::has_fcfids() && VM_Version::has_mtfprd()); + ins_cost(DEFAULT_COST); + + expand %{ + regD tmpD; + moveL2D_reg(tmpD, src); + convL2FRaw_regF(dst, tmpD); // Convert to float. + %} +%} + // Moved up as used in expand. //instruct convD2F_reg(regF dst, regD src) %{%} @@ -10951,6 +11270,7 @@ instruct convL2F_ireg_fcfids_Ex(regF dst, iRegLsrc src) %{ // Integer to Double conversion. instruct convI2D_reg_Ex(regD dst, iRegIsrc src) %{ match(Set dst (ConvI2D src)); + predicate(!VM_Version::has_mtfprd()); ins_cost(DEFAULT_COST); expand %{ @@ -10964,6 +11284,19 @@ instruct convI2D_reg_Ex(regD dst, iRegIsrc src) %{ %} %} +// Integer to Double conversion. Special version for Power8. +instruct convI2D_reg_mtfprd_Ex(regD dst, iRegIsrc src) %{ + match(Set dst (ConvI2D src)); + predicate(VM_Version::has_mtfprd()); + ins_cost(DEFAULT_COST); + + expand %{ + regD tmpD; + moveI2D_reg(tmpD, src); + convL2DRaw_regD(dst, tmpD); // Convert to double. + %} +%} + // Long to Double conversion instruct convL2D_reg_Ex(regD dst, stackSlotL src) %{ match(Set dst (ConvL2D src)); @@ -10976,6 +11309,19 @@ instruct convL2D_reg_Ex(regD dst, stackSlotL src) %{ %} %} +// Long to Double conversion. Special version for Power8. +instruct convL2D_reg_mtfprd_Ex(regD dst, iRegLsrc src) %{ + match(Set dst (ConvL2D src)); + predicate(VM_Version::has_mtfprd()); + ins_cost(DEFAULT_COST); + + expand %{ + regD tmpD; + moveL2D_reg(tmpD, src); + convL2DRaw_regD(dst, tmpD); // Convert to double. + %} +%} + instruct convF2D_reg(regD dst, regF src) %{ match(Set dst (ConvF2D src)); format %{ "FMR $dst, $src \t// float->double" %} @@ -12705,8 +13051,7 @@ instruct insrwi(iRegIdst dst, iRegIsrc src, immI16 pos, immI16 shift) %{ // Just slightly faster than java implementation. instruct bytes_reverse_int_Ex(iRegIdst dst, iRegIsrc src) %{ match(Set dst (ReverseBytesI src)); - predicate(UseCountLeadingZerosInstructionsPPC64); - ins_cost(DEFAULT_COST); + ins_cost(7*DEFAULT_COST); expand %{ immI16 imm24 %{ (int) 24 %} @@ -12728,6 +13073,172 @@ instruct bytes_reverse_int_Ex(iRegIdst dst, iRegIsrc src) %{ %} %} +instruct bytes_reverse_long_Ex(iRegLdst dst, iRegLsrc src) %{ + match(Set dst (ReverseBytesL src)); + ins_cost(15*DEFAULT_COST); + + expand %{ + immI16 imm56 %{ (int) 56 %} + immI16 imm48 %{ (int) 48 %} + immI16 imm40 %{ (int) 40 %} + immI16 imm32 %{ (int) 32 %} + immI16 imm24 %{ (int) 24 %} + immI16 imm16 %{ (int) 16 %} + immI16 imm8 %{ (int) 8 %} + immI16 imm0 %{ (int) 0 %} + iRegLdst tmpL1; + iRegLdst tmpL2; + iRegLdst tmpL3; + iRegLdst tmpL4; + iRegLdst tmpL5; + iRegLdst tmpL6; + + // src : |a|b|c|d|e|f|g|h| + rldicl(tmpL1, src, imm8, imm24); // tmpL1 : | | | |e|f|g|h|a| + rldicl(tmpL2, tmpL1, imm32, imm24); // tmpL2 : | | | |a| | | |e| + rldicl(tmpL3, tmpL2, imm32, imm0); // tmpL3 : | | | |e| | | |a| + rldicl(tmpL1, src, imm16, imm24); // tmpL1 : | | | |f|g|h|a|b| + rldicl(tmpL2, tmpL1, imm32, imm24); // tmpL2 : | | | |b| | | |f| + rldicl(tmpL4, tmpL2, imm40, imm0); // tmpL4 : | | |f| | | |b| | + orL_reg_reg(tmpL5, tmpL3, tmpL4); // tmpL5 : | | |f|e| | |b|a| + rldicl(tmpL1, src, imm24, imm24); // tmpL1 : | | | |g|h|a|b|c| + rldicl(tmpL2, tmpL1, imm32, imm24); // tmpL2 : | | | |c| | | |g| + rldicl(tmpL3, tmpL2, imm48, imm0); // tmpL3 : | |g| | | |c| | | + rldicl(tmpL1, src, imm32, imm24); // tmpL1 : | | | |h|a|b|c|d| + rldicl(tmpL2, tmpL1, imm32, imm24); // tmpL2 : | | | |d| | | |h| + rldicl(tmpL4, tmpL2, imm56, imm0); // tmpL4 : |h| | | |d| | | | + orL_reg_reg(tmpL6, tmpL3, tmpL4); // tmpL6 : |h|g| | |d|c| | | + orL_reg_reg(dst, tmpL5, tmpL6); // dst : |h|g|f|e|d|c|b|a| + %} +%} + +instruct bytes_reverse_ushort_Ex(iRegIdst dst, iRegIsrc src) %{ + match(Set dst (ReverseBytesUS src)); + ins_cost(2*DEFAULT_COST); + + expand %{ + immI16 imm16 %{ (int) 16 %} + immI16 imm8 %{ (int) 8 %} + + urShiftI_reg_imm(dst, src, imm8); + insrwi(dst, src, imm16, imm8); + %} +%} + +instruct bytes_reverse_short_Ex(iRegIdst dst, iRegIsrc src) %{ + match(Set dst (ReverseBytesS src)); + ins_cost(3*DEFAULT_COST); + + expand %{ + immI16 imm16 %{ (int) 16 %} + immI16 imm8 %{ (int) 8 %} + iRegLdst tmpI1; + + urShiftI_reg_imm(tmpI1, src, imm8); + insrwi(tmpI1, src, imm16, imm8); + extsh(dst, tmpI1); + %} +%} + +// Load Integer reversed byte order +instruct loadI_reversed(iRegIdst dst, indirect mem) %{ + match(Set dst (ReverseBytesI (LoadI mem))); + ins_cost(MEMORY_REF_COST); + + size(4); + ins_encode %{ + __ lwbrx($dst$$Register, $mem$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Load Long - aligned and reversed +instruct loadL_reversed(iRegLdst dst, indirect mem) %{ + match(Set dst (ReverseBytesL (LoadL mem))); + predicate(VM_Version::has_ldbrx()); + ins_cost(MEMORY_REF_COST); + + size(4); + ins_encode %{ + __ ldbrx($dst$$Register, $mem$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Load unsigned short / char reversed byte order +instruct loadUS_reversed(iRegIdst dst, indirect mem) %{ + match(Set dst (ReverseBytesUS (LoadUS mem))); + ins_cost(MEMORY_REF_COST); + + size(4); + ins_encode %{ + __ lhbrx($dst$$Register, $mem$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Load short reversed byte order +instruct loadS_reversed(iRegIdst dst, indirect mem) %{ + match(Set dst (ReverseBytesS (LoadS mem))); + ins_cost(MEMORY_REF_COST + DEFAULT_COST); + + size(8); + ins_encode %{ + __ lhbrx($dst$$Register, $mem$$Register); + __ extsh($dst$$Register, $dst$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Store Integer reversed byte order +instruct storeI_reversed(iRegIsrc src, indirect mem) %{ + match(Set mem (StoreI mem (ReverseBytesI src))); + ins_cost(MEMORY_REF_COST); + + size(4); + ins_encode %{ + __ stwbrx($src$$Register, $mem$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Store Long reversed byte order +instruct storeL_reversed(iRegLsrc src, indirect mem) %{ + match(Set mem (StoreL mem (ReverseBytesL src))); + predicate(VM_Version::has_stdbrx()); + ins_cost(MEMORY_REF_COST); + + size(4); + ins_encode %{ + __ stdbrx($src$$Register, $mem$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Store unsigned short / char reversed byte order +instruct storeUS_reversed(iRegIsrc src, indirect mem) %{ + match(Set mem (StoreC mem (ReverseBytesUS src))); + ins_cost(MEMORY_REF_COST); + + size(4); + ins_encode %{ + __ sthbrx($src$$Register, $mem$$Register); + %} + ins_pipe(pipe_class_default); +%} + +// Store short reversed byte order +instruct storeS_reversed(iRegIsrc src, indirect mem) %{ + match(Set mem (StoreC mem (ReverseBytesS src))); + ins_cost(MEMORY_REF_COST); + + size(4); + ins_encode %{ + __ sthbrx($src$$Register, $mem$$Register); + %} + ins_pipe(pipe_class_default); +%} + //---------- Replicate Vector Instructions ------------------------------------ // Insrdi does replicate if src == dst. diff --git a/hotspot/src/cpu/ppc/vm/register_ppc.cpp b/hotspot/src/cpu/ppc/vm/register_ppc.cpp index 8dcd325ad75..1428fef704a 100644 --- a/hotspot/src/cpu/ppc/vm/register_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/register_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2013 SAP SE. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 SAP SE. 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 @@ -81,8 +81,17 @@ const char* VectorSRegisterImpl::name() const { "VSR0", "VSR1", "VSR2", "VSR3", "VSR4", "VSR5", "VSR6", "VSR7", "VSR8", "VSR9", "VSR10", "VSR11", "VSR12", "VSR13", "VSR14", "VSR15", "VSR16", "VSR17", "VSR18", "VSR19", "VSR20", "VSR21", "VSR22", "VSR23", - "VSR24", "VSR25", "VSR26", "VSR27", "VSR28", "VSR29", "VSR30", "VSR31" + "VSR24", "VSR25", "VSR26", "VSR27", "VSR28", "VSR29", "VSR30", "VSR31", + "VSR32", "VSR33", "VSR34", "VSR35", "VSR36", "VSR37", "VSR38", "VSR39", + "VSR40", "VSR41", "VSR42", "VSR43", "VSR44", "VSR45", "VSR46", "VSR47", + "VSR48", "VSR49", "VSR50", "VSR51", "VSR52", "VSR53", "VSR54", "VSR55", + "VSR56", "VSR57", "VSR58", "VSR59", "VSR60", "VSR61", "VSR62", "VSR63" }; return is_valid() ? names[encoding()] : "vsnoreg"; } +// Method to convert a VectorRegister to a Vector-Scalar Register (VectorSRegister) +VectorSRegister VectorRegisterImpl::to_vsr() const { + if (this == vnoreg) { return vsnoregi; } + return as_VectorSRegister(encoding() + 32); +} diff --git a/hotspot/src/cpu/ppc/vm/register_ppc.hpp b/hotspot/src/cpu/ppc/vm/register_ppc.hpp index e73dc18a30a..c554f88619d 100644 --- a/hotspot/src/cpu/ppc/vm/register_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/register_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 SAP SE. 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 @@ -398,6 +398,11 @@ inline VectorRegister as_VectorRegister(int encoding) { return (VectorRegister)(intptr_t)encoding; } +// Forward declaration +// Use VectorSRegister as a shortcut. +class VectorSRegisterImpl; +typedef VectorSRegisterImpl* VectorSRegister; + // The implementation of vector registers for the Power architecture class VectorRegisterImpl: public AbstractRegisterImpl { public: @@ -415,6 +420,9 @@ class VectorRegisterImpl: public AbstractRegisterImpl { bool is_valid() const { return 0 <= value() && value() < number_of_registers; } const char* name() const; + + // convert to VSR + VectorSRegister to_vsr() const; }; // The Vector registers of the Power architecture @@ -491,10 +499,6 @@ CONSTANT_REGISTER_DECLARATION(VectorRegister, VR31, (31)); #endif // DONT_USE_REGISTER_DEFINES -// Use VectorSRegister as a shortcut. -class VectorSRegisterImpl; -typedef VectorSRegisterImpl* VectorSRegister; - inline VectorSRegister as_VectorSRegister(int encoding) { return (VectorSRegister)(intptr_t)encoding; } @@ -503,7 +507,7 @@ inline VectorSRegister as_VectorSRegister(int encoding) { class VectorSRegisterImpl: public AbstractRegisterImpl { public: enum { - number_of_registers = 32 + number_of_registers = 64 }; // construction @@ -554,6 +558,38 @@ CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR28, (28)); CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR29, (29)); CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR30, (30)); CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR31, (31)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR32, (32)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR33, (33)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR34, (34)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR35, (35)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR36, (36)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR37, (37)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR38, (38)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR39, (39)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR40, (40)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR41, (41)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR42, (42)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR43, (43)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR44, (44)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR45, (45)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR46, (46)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR47, (47)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR48, (48)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR49, (49)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR50, (50)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR51, (51)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR52, (52)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR53, (53)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR54, (54)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR55, (55)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR56, (56)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR57, (57)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR58, (58)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR59, (59)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR60, (60)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR61, (61)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR62, (62)); +CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR63, (63)); #ifndef DONT_USE_REGISTER_DEFINES #define vsnoregi ((VectorSRegister)(vsnoreg_VectorSRegisterEnumValue)) @@ -589,6 +625,38 @@ CONSTANT_REGISTER_DECLARATION(VectorSRegister, VSR31, (31)); #define VSR29 ((VectorSRegister)( VSR29_VectorSRegisterEnumValue)) #define VSR30 ((VectorSRegister)( VSR30_VectorSRegisterEnumValue)) #define VSR31 ((VectorSRegister)( VSR31_VectorSRegisterEnumValue)) +#define VSR32 ((VectorSRegister)( VSR32_VectorSRegisterEnumValue)) +#define VSR33 ((VectorSRegister)( VSR33_VectorSRegisterEnumValue)) +#define VSR34 ((VectorSRegister)( VSR34_VectorSRegisterEnumValue)) +#define VSR35 ((VectorSRegister)( VSR35_VectorSRegisterEnumValue)) +#define VSR36 ((VectorSRegister)( VSR36_VectorSRegisterEnumValue)) +#define VSR37 ((VectorSRegister)( VSR37_VectorSRegisterEnumValue)) +#define VSR38 ((VectorSRegister)( VSR38_VectorSRegisterEnumValue)) +#define VSR39 ((VectorSRegister)( VSR39_VectorSRegisterEnumValue)) +#define VSR40 ((VectorSRegister)( VSR40_VectorSRegisterEnumValue)) +#define VSR41 ((VectorSRegister)( VSR41_VectorSRegisterEnumValue)) +#define VSR42 ((VectorSRegister)( VSR42_VectorSRegisterEnumValue)) +#define VSR43 ((VectorSRegister)( VSR43_VectorSRegisterEnumValue)) +#define VSR44 ((VectorSRegister)( VSR44_VectorSRegisterEnumValue)) +#define VSR45 ((VectorSRegister)( VSR45_VectorSRegisterEnumValue)) +#define VSR46 ((VectorSRegister)( VSR46_VectorSRegisterEnumValue)) +#define VSR47 ((VectorSRegister)( VSR47_VectorSRegisterEnumValue)) +#define VSR48 ((VectorSRegister)( VSR48_VectorSRegisterEnumValue)) +#define VSR49 ((VectorSRegister)( VSR49_VectorSRegisterEnumValue)) +#define VSR50 ((VectorSRegister)( VSR50_VectorSRegisterEnumValue)) +#define VSR51 ((VectorSRegister)( VSR51_VectorSRegisterEnumValue)) +#define VSR52 ((VectorSRegister)( VSR52_VectorSRegisterEnumValue)) +#define VSR53 ((VectorSRegister)( VSR53_VectorSRegisterEnumValue)) +#define VSR54 ((VectorSRegister)( VSR54_VectorSRegisterEnumValue)) +#define VSR55 ((VectorSRegister)( VSR55_VectorSRegisterEnumValue)) +#define VSR56 ((VectorSRegister)( VSR56_VectorSRegisterEnumValue)) +#define VSR57 ((VectorSRegister)( VSR57_VectorSRegisterEnumValue)) +#define VSR58 ((VectorSRegister)( VSR58_VectorSRegisterEnumValue)) +#define VSR59 ((VectorSRegister)( VSR59_VectorSRegisterEnumValue)) +#define VSR60 ((VectorSRegister)( VSR60_VectorSRegisterEnumValue)) +#define VSR61 ((VectorSRegister)( VSR61_VectorSRegisterEnumValue)) +#define VSR62 ((VectorSRegister)( VSR62_VectorSRegisterEnumValue)) +#define VSR63 ((VectorSRegister)( VSR63_VectorSRegisterEnumValue)) #endif // DONT_USE_REGISTER_DEFINES // Maximum number of incoming arguments that can be passed in i registers. @@ -609,7 +677,7 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl { * 2 // register halves + ConditionRegisterImpl::number_of_registers // condition code registers + SpecialRegisterImpl::number_of_registers // special registers - + VectorRegisterImpl::number_of_registers // vector registers + + VectorRegisterImpl::number_of_registers // VSX registers }; static const int max_gpr; diff --git a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp index dc36aa77da2..20a1a963abc 100644 --- a/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/sharedRuntime_ppc.cpp @@ -35,6 +35,7 @@ #include "oops/compiledICHolder.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/align.hpp" #include "vmreg_ppc.inline.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" @@ -221,7 +222,7 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble const int regstosave_num = sizeof(RegisterSaver_LiveRegs) / sizeof(RegisterSaver::LiveRegType); const int register_save_size = regstosave_num * reg_size; - const int frame_size_in_bytes = round_to(register_save_size, frame::alignment_in_bytes) + const int frame_size_in_bytes = align_up(register_save_size, frame::alignment_in_bytes) + frame::abi_reg_args_size; *out_frame_size_in_bytes = frame_size_in_bytes; const int frame_size_in_slots = frame_size_in_bytes / sizeof(jint); @@ -658,7 +659,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt, ShouldNotReachHere(); } } - return round_to(stk, 2); + return align_up(stk, 2); } #if defined(COMPILER1) || defined(COMPILER2) @@ -845,7 +846,7 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt, } } - return round_to(stk, 2); + return align_up(stk, 2); } #endif // COMPILER2 @@ -873,7 +874,7 @@ static address gen_c2i_adapter(MacroAssembler *masm, // Adapter needs TOP_IJAVA_FRAME_ABI. const int adapter_size = frame::top_ijava_frame_abi_size + - round_to(total_args_passed * wordSize, frame::alignment_in_bytes); + align_up(total_args_passed * wordSize, frame::alignment_in_bytes); // regular (verified) c2i entry point c2i_entrypoint = __ pc(); @@ -1022,9 +1023,9 @@ void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm, // number (all values in registers) or the maximum stack slot accessed. // Convert 4-byte c2 stack slots to words. - comp_words_on_stack = round_to(comp_args_on_stack*VMRegImpl::stack_slot_size, wordSize)>>LogBytesPerWord; + comp_words_on_stack = align_up(comp_args_on_stack*VMRegImpl::stack_slot_size, wordSize)>>LogBytesPerWord; // Round up to miminum stack alignment, in wordSize. - comp_words_on_stack = round_to(comp_words_on_stack, 2); + comp_words_on_stack = align_up(comp_words_on_stack, 2); __ resize_frame(-comp_words_on_stack * wordSize, R11_scratch1); } @@ -1609,7 +1610,7 @@ static void unpack_array_argument(MacroAssembler* masm, VMRegPair reg, BasicType } static void verify_oop_args(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, const BasicType* sig_bt, const VMRegPair* regs) { Register temp_reg = R19_method; // not part of any compiled calling seq @@ -1631,7 +1632,7 @@ static void verify_oop_args(MacroAssembler* masm, } static void gen_special_dispatch(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, const BasicType* sig_bt, const VMRegPair* regs) { verify_oop_args(masm, method, sig_bt, regs); @@ -1918,7 +1919,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, } } } - total_save_slots = double_slots * 2 + round_to(single_slots, 2); // round to even + total_save_slots = double_slots * 2 + align_up(single_slots, 2); // round to even } int oop_handle_slot_offset = stack_slots; @@ -1945,7 +1946,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, // Now compute actual number of stack words we need. // Rounding to make stack properly aligned. - stack_slots = round_to(stack_slots, // 7) + stack_slots = align_up(stack_slots, // 7) frame::alignment_in_bytes / VMRegImpl::stack_slot_size); int frame_size_in_bytes = stack_slots * VMRegImpl::stack_slot_size; @@ -2203,8 +2204,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, // disallows any pending_exception. // Save argument registers and leave room for C-compatible ABI_REG_ARGS. - int frame_size = frame::abi_reg_args_size + - round_to(total_c_args * wordSize, frame::alignment_in_bytes); + int frame_size = frame::abi_reg_args_size + align_up(total_c_args * wordSize, frame::alignment_in_bytes); __ mr(R11_scratch1, R1_SP); RegisterSaver::push_frame_and_save_argument_registers(masm, R12_scratch2, frame_size, total_c_args, out_regs, out_regs2); @@ -2570,7 +2570,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, // This function returns the adjust size (in number of words) to a c2i adapter // activation for use during deoptimization. int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals) { - return round_to((callee_locals - callee_parameters) * Interpreter::stackElementWords, frame::alignment_in_bytes); + return align_up((callee_locals - callee_parameters) * Interpreter::stackElementWords, frame::alignment_in_bytes); } uint SharedRuntime::out_preserve_stack_slots() { diff --git a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp index 4bd0c833ab8..339152c5ff3 100644 --- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, SAP SE. 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 @@ -38,6 +38,7 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/thread.inline.hpp" +#include "utilities/align.hpp" #define __ _masm-> @@ -626,7 +627,7 @@ class StubGenerator: public StubCodeGenerator { int spill_slots = 3; if (preserve1 != noreg) { spill_slots++; } if (preserve2 != noreg) { spill_slots++; } - const int frame_size = align_size_up(frame::abi_reg_args_size + spill_slots * BytesPerWord, frame::alignment_in_bytes); + const int frame_size = align_up(frame::abi_reg_args_size + spill_slots * BytesPerWord, frame::alignment_in_bytes); Label filtered; // Is marking active? @@ -687,7 +688,7 @@ class StubGenerator: public StubCodeGenerator { case BarrierSet::G1SATBCTLogging: { int spill_slots = (preserve != noreg) ? 1 : 0; - const int frame_size = align_size_up(frame::abi_reg_args_size + spill_slots * BytesPerWord, frame::alignment_in_bytes); + const int frame_size = align_up(frame::abi_reg_args_size + spill_slots * BytesPerWord, frame::alignment_in_bytes); __ save_LR_CR(R0); __ push_frame(frame_size, R0); @@ -2728,7 +2729,7 @@ class StubGenerator: public StubCodeGenerator { __ vspltisb (vTmp2, -16); __ vrld (keyPerm, keyPerm, vTmp2); __ vrld (keyPerm, keyPerm, vTmp2); - __ vsldoi (keyPerm, keyPerm, keyPerm, -8); + __ vsldoi (keyPerm, keyPerm, keyPerm, 8); // load the 1st round key to vKey1 __ li (keypos, 0); @@ -2928,7 +2929,7 @@ class StubGenerator: public StubCodeGenerator { __ vspltisb (vTmp2, -16); __ vrld (keyPerm, keyPerm, vTmp2); __ vrld (keyPerm, keyPerm, vTmp2); - __ vsldoi (keyPerm, keyPerm, keyPerm, -8); + __ vsldoi (keyPerm, keyPerm, keyPerm, 8); __ cmpwi (CCR0, keylen, 44); __ beq (CCR0, L_do44); @@ -3276,6 +3277,36 @@ class StubGenerator: public StubCodeGenerator { return start; } + + // Compute CRC32/CRC32C function. + void generate_CRC_updateBytes(const char* name, Register table, bool invertCRC) { + + // arguments to kernel_crc32: + const Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call. + const Register data = R4_ARG2; // source byte array + const Register dataLen = R5_ARG3; // #bytes to process + + const Register t0 = R2; + const Register t1 = R7; + const Register t2 = R8; + const Register t3 = R9; + const Register tc0 = R10; + const Register tc1 = R11; + const Register tc2 = R12; + + BLOCK_COMMENT("Stub body {"); + assert_different_registers(crc, data, dataLen, table); + + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, table, invertCRC); + + BLOCK_COMMENT("return"); + __ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET). + __ blr(); + + BLOCK_COMMENT("} Stub body"); + } + + /** * Arguments: * @@ -3296,14 +3327,14 @@ class StubGenerator: public StubCodeGenerator { StubCodeMark mark(this, "StubRoutines", name); address start = __ function_entry(); // Remember stub start address (is rtn value). + const Register table = R6; // crc table address + +#ifdef VM_LITTLE_ENDIAN // arguments to kernel_crc32: const Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call. const Register data = R4_ARG2; // source byte array const Register dataLen = R5_ARG3; // #bytes to process - const Register table = R6; // crc table address - -#ifdef VM_LITTLE_ENDIAN if (VM_Version::has_vpmsumb()) { const Register constants = R2; // constants address const Register bconstants = R8; // barret table address @@ -3321,7 +3352,7 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::ppc64::generate_load_crc_constants_addr(_masm, constants); StubRoutines::ppc64::generate_load_crc_barret_constants_addr(_masm, bconstants); - __ kernel_crc32_1word_vpmsumd(crc, data, dataLen, table, constants, bconstants, t0, t1, t2, t3, t4); + __ kernel_crc32_1word_vpmsumd(crc, data, dataLen, table, constants, bconstants, t0, t1, t2, t3, t4, true); BLOCK_COMMENT("return"); __ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET). @@ -3331,31 +3362,79 @@ class StubGenerator: public StubCodeGenerator { } else #endif { - const Register t0 = R2; - const Register t1 = R7; - const Register t2 = R8; - const Register t3 = R9; - const Register tc0 = R10; - const Register tc1 = R11; - const Register tc2 = R12; + StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table); + generate_CRC_updateBytes(name, table, true); + } + + return start; + } + + + /** + * Arguments: + * + * Inputs: + * R3_ARG1 - int crc + * R4_ARG2 - byte* buf + * R5_ARG3 - int length (of buffer) + * + * scratch: + * R2, R6-R12 + * + * Ouput: + * R3_RET - int crc result + */ + // Compute CRC32C function. + address generate_CRC32C_updateBytes(const char* name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ function_entry(); // Remember stub start address (is rtn value). + + const Register table = R6; // crc table address + +#if 0 // no vector support yet for CRC32C +#ifdef VM_LITTLE_ENDIAN + // arguments to kernel_crc32: + const Register crc = R3_ARG1; // Current checksum, preset by caller or result from previous call. + const Register data = R4_ARG2; // source byte array + const Register dataLen = R5_ARG3; // #bytes to process + + if (VM_Version::has_vpmsumb()) { + const Register constants = R2; // constants address + const Register bconstants = R8; // barret table address + + const Register t0 = R9; + const Register t1 = R10; + const Register t2 = R11; + const Register t3 = R12; + const Register t4 = R7; BLOCK_COMMENT("Stub body {"); assert_different_registers(crc, data, dataLen, table); - StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table); + StubRoutines::ppc64::generate_load_crc32c_table_addr(_masm, table); + StubRoutines::ppc64::generate_load_crc32c_constants_addr(_masm, constants); + StubRoutines::ppc64::generate_load_crc32c_barret_constants_addr(_masm, bconstants); - __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, table); + __ kernel_crc32_1word_vpmsumd(crc, data, dataLen, table, constants, bconstants, t0, t1, t2, t3, t4, false); BLOCK_COMMENT("return"); __ mr_if_needed(R3_RET, crc); // Updated crc is function result. No copying required (R3_ARG1 == R3_RET). __ blr(); BLOCK_COMMENT("} Stub body"); + } else +#endif +#endif + { + StubRoutines::ppc64::generate_load_crc32c_table_addr(_masm, table); + generate_CRC_updateBytes(name, table, false); } return start; } + // Initialization void generate_initial() { // Generates all stubs and initializes the entry points @@ -3383,6 +3462,12 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_crc_table_adr = (address)StubRoutines::ppc64::_crc_table; StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes("CRC32_updateBytes"); } + + // CRC32C Intrinsics. + if (UseCRC32CIntrinsics) { + StubRoutines::_crc32c_table_addr = (address)StubRoutines::ppc64::_crc32c_table; + StubRoutines::_updateBytesCRC32C = generate_CRC32C_updateBytes("CRC32C_updateBytes"); + } } void generate_all() { diff --git a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc.hpp b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc.hpp index 5b5b2c270dd..dcda6be8a76 100644 --- a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, SAP SE. 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 @@ -55,13 +55,16 @@ class ppc64 { // CRC32 Intrinsics. static juint _crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE]; + static juint _crc32c_table[CRC32_TABLES][CRC32_COLUMN_SIZE]; static juint* _constants; static juint* _barret_constants; public: // CRC32 Intrinsics. + static void generate_load_table_addr(MacroAssembler* masm, Register table, address table_addr, uint64_t table_contents); static void generate_load_crc_table_addr(MacroAssembler* masm, Register table); + static void generate_load_crc32c_table_addr(MacroAssembler* masm, Register table); static void generate_load_crc_constants_addr(MacroAssembler* masm, Register table); static void generate_load_crc_barret_constants_addr(MacroAssembler* masm, Register table); static juint* generate_crc_constants(); diff --git a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp index 088d63a2f79..f5591669bcd 100644 --- a/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/stubRoutines_ppc_64.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, SAP SE. 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 @@ -32,7 +32,11 @@ #define __ masm-> -// CRC32 Intrinsics. +// CRC32(C) Intrinsics. +void StubRoutines::ppc64::generate_load_crc32c_table_addr(MacroAssembler* masm, Register table) { + __ load_const_optimized(table, StubRoutines::_crc32c_table_addr, R0); +} + void StubRoutines::ppc64::generate_load_crc_table_addr(MacroAssembler* masm, Register table) { __ load_const_optimized(table, StubRoutines::_crc_table_adr, R0); } @@ -347,441 +351,592 @@ juint* StubRoutines::ppc64::generate_crc_barret_constants() { * crc_table[] from jdk/src/share/native/java/util/zip/zlib-1.2.8/crc32.h */ juint StubRoutines::ppc64::_crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE] = { - { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL -#ifdef CRC32_BYFOUR - }, - { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, - 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, - 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, - 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, - 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, - 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, - 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, - 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, - 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, - 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, - 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, - 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, - 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, - 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, - 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, - 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, - 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, - 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, - 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, - 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, - 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, - 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, - 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, - 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, - 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, - 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, - 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, - 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, - 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, - 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, - 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, - 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, - 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, - 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, - 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, - 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, - 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, - 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, - 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, - 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, - 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, - 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, - 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, - 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, - 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, - 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, - 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, - 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, - 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, - 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, - 0x9324fd72UL - }, - { - 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, - 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, - 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, - 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, - 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, - 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, - 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, - 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, - 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, - 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, - 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, - 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, - 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, - 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, - 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, - 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, - 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, - 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, - 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, - 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, - 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, - 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, - 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, - 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, - 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, - 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, - 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, - 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, - 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, - 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, - 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, - 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, - 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, - 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, - 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, - 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, - 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, - 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, - 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, - 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, - 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, - 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, - 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, - 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, - 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, - 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, - 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, - 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, - 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, - 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, - 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, - 0xbe9834edUL - }, - { - 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, - 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, - 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, - 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, - 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, - 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, - 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, - 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, - 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, - 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, - 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, - 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, - 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, - 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, - 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, - 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, - 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, - 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, - 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, - 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, - 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, - 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, - 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, - 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, - 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, - 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, - 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, - 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, - 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, - 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, - 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, - 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, - 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, - 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, - 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, - 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, - 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, - 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, - 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, - 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, - 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, - 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, - 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, - 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, - 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, - 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, - 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, - 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, - 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, - 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, - 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, - 0xde0506f1UL - }, - { - 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, - 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, - 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, - 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, - 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, - 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, - 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, - 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, - 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, - 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, - 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, - 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, - 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, - 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, - 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, - 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, - 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, - 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, - 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, - 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, - 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, - 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, - 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, - 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, - 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, - 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, - 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, - 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, - 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, - 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, - 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, - 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, - 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, - 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, - 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, - 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, - 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, - 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, - 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, - 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, - 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, - 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, - 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, - 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, - 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, - 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, - 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, - 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, - 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, - 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, - 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, - 0x8def022dUL - }, - { - 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, - 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, - 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, - 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, - 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, - 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, - 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, - 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, - 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, - 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, - 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, - 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, - 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, - 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, - 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, - 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, - 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, - 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, - 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, - 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, - 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, - 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, - 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, - 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, - 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, - 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, - 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, - 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, - 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, - 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, - 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, - 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, - 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, - 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, - 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, - 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, - 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, - 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, - 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, - 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, - 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, - 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, - 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, - 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, - 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, - 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, - 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, - 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, - 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, - 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, - 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, - 0x72fd2493UL - }, - { - 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, - 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, - 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, - 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, - 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, - 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, - 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, - 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, - 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, - 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, - 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, - 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, - 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, - 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, - 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, - 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, - 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, - 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, - 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, - 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, - 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, - 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, - 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, - 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, - 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, - 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, - 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, - 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, - 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, - 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, - 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, - 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, - 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, - 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, - 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, - 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, - 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, - 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, - 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, - 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, - 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, - 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, - 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, - 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, - 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, - 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, - 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, - 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, - 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, - 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, - 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, - 0xed3498beUL - }, - { - 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, - 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, - 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, - 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, - 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, - 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, - 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, - 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, - 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, - 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, - 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, - 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, - 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, - 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, - 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, - 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, - 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, - 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, - 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, - 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, - 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, - 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, - 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, - 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, - 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, - 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, - 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, - 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, - 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, - 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, - 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, - 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, - 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, - 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, - 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, - 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, - 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, - 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, - 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, - 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, - 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, - 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, - 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, - 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, - 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, - 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, - 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, - 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, - 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, - 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, - 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, - 0xf10605deUL -#endif - } -}; + /* polyBits = 7976584769 0x00000001db710641L, shifted = 0xedb88320 */ + /* CRC32 table for single bytes, auto-generated. DO NOT MODIFY! */ + /* CRC32 table 0 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 0x706af48fU, 0xe963a535U, 0x9e6495a3U + /* 8 */ , 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U + /* 16 */ , 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U + /* 24 */ , 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, 0xfa0f3d63U, 0x8d080df5U + /* 32 */ , 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU + /* 40 */ , 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U + /* 48 */ , 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, 0xb8bda50fU + /* 56 */ , 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU + /* 64 */ , 0x76dc4190U, 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, 0xe8b8d433U + /* 72 */ , 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U + /* 80 */ , 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U + /* 88 */ , 0x65b0d9c6U, 0x12b7e950U, 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U + /* 96 */ , 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU + /* 104 */ , 0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U + /* 112 */ , 0x5005713cU, 0x270241aaU, 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU + /* 120 */ , 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU + /* 128 */ , 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U + /* 136 */ , 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U + /* 144 */ , 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, 0x196c3671U, 0x6e6b06e7U + /* 152 */ , 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U + /* 160 */ , 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU + /* 168 */ , 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, 0x4669be79U + /* 176 */ , 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU + /* 184 */ , 0xc5ba3bbeU, 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bdeae1dU + /* 192 */ , 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U + /* 200 */ , 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U + /* 208 */ , 0x86d3d2d4U, 0xf1d4e242U, 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b74777U + /* 216 */ , 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U + /* 224 */ , 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU + /* 232 */ , 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U + /* 240 */ , 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, 0xcdd70693U, 0x54de5729U, 0x23d967bfU + /* 248 */ , 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU + } + #ifdef CRC32_BYFOUR + , + /* CRC32 table 1 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x191b3141U, 0x32366282U, 0x2b2d53c3U, 0x646cc504U, 0x7d77f445U, 0x565aa786U, 0x4f4196c7U + /* 8 */ , 0xc8d98a08U, 0xd1c2bb49U, 0xfaefe88aU, 0xe3f4d9cbU, 0xacb54f0cU, 0xb5ae7e4dU, 0x9e832d8eU, 0x87981ccfU + /* 16 */ , 0x4ac21251U, 0x53d92310U, 0x78f470d3U, 0x61ef4192U, 0x2eaed755U, 0x37b5e614U, 0x1c98b5d7U, 0x05838496U + /* 24 */ , 0x821b9859U, 0x9b00a918U, 0xb02dfadbU, 0xa936cb9aU, 0xe6775d5dU, 0xff6c6c1cU, 0xd4413fdfU, 0xcd5a0e9eU + /* 32 */ , 0x958424a2U, 0x8c9f15e3U, 0xa7b24620U, 0xbea97761U, 0xf1e8e1a6U, 0xe8f3d0e7U, 0xc3de8324U, 0xdac5b265U + /* 40 */ , 0x5d5daeaaU, 0x44469febU, 0x6f6bcc28U, 0x7670fd69U, 0x39316baeU, 0x202a5aefU, 0x0b07092cU, 0x121c386dU + /* 48 */ , 0xdf4636f3U, 0xc65d07b2U, 0xed705471U, 0xf46b6530U, 0xbb2af3f7U, 0xa231c2b6U, 0x891c9175U, 0x9007a034U + /* 56 */ , 0x179fbcfbU, 0x0e848dbaU, 0x25a9de79U, 0x3cb2ef38U, 0x73f379ffU, 0x6ae848beU, 0x41c51b7dU, 0x58de2a3cU + /* 64 */ , 0xf0794f05U, 0xe9627e44U, 0xc24f2d87U, 0xdb541cc6U, 0x94158a01U, 0x8d0ebb40U, 0xa623e883U, 0xbf38d9c2U + /* 72 */ , 0x38a0c50dU, 0x21bbf44cU, 0x0a96a78fU, 0x138d96ceU, 0x5ccc0009U, 0x45d73148U, 0x6efa628bU, 0x77e153caU + /* 80 */ , 0xbabb5d54U, 0xa3a06c15U, 0x888d3fd6U, 0x91960e97U, 0xded79850U, 0xc7cca911U, 0xece1fad2U, 0xf5facb93U + /* 88 */ , 0x7262d75cU, 0x6b79e61dU, 0x4054b5deU, 0x594f849fU, 0x160e1258U, 0x0f152319U, 0x243870daU, 0x3d23419bU + /* 96 */ , 0x65fd6ba7U, 0x7ce65ae6U, 0x57cb0925U, 0x4ed03864U, 0x0191aea3U, 0x188a9fe2U, 0x33a7cc21U, 0x2abcfd60U + /* 104 */ , 0xad24e1afU, 0xb43fd0eeU, 0x9f12832dU, 0x8609b26cU, 0xc94824abU, 0xd05315eaU, 0xfb7e4629U, 0xe2657768U + /* 112 */ , 0x2f3f79f6U, 0x362448b7U, 0x1d091b74U, 0x04122a35U, 0x4b53bcf2U, 0x52488db3U, 0x7965de70U, 0x607eef31U + /* 120 */ , 0xe7e6f3feU, 0xfefdc2bfU, 0xd5d0917cU, 0xcccba03dU, 0x838a36faU, 0x9a9107bbU, 0xb1bc5478U, 0xa8a76539U + /* 128 */ , 0x3b83984bU, 0x2298a90aU, 0x09b5fac9U, 0x10aecb88U, 0x5fef5d4fU, 0x46f46c0eU, 0x6dd93fcdU, 0x74c20e8cU + /* 136 */ , 0xf35a1243U, 0xea412302U, 0xc16c70c1U, 0xd8774180U, 0x9736d747U, 0x8e2de606U, 0xa500b5c5U, 0xbc1b8484U + /* 144 */ , 0x71418a1aU, 0x685abb5bU, 0x4377e898U, 0x5a6cd9d9U, 0x152d4f1eU, 0x0c367e5fU, 0x271b2d9cU, 0x3e001cddU + /* 152 */ , 0xb9980012U, 0xa0833153U, 0x8bae6290U, 0x92b553d1U, 0xddf4c516U, 0xc4eff457U, 0xefc2a794U, 0xf6d996d5U + /* 160 */ , 0xae07bce9U, 0xb71c8da8U, 0x9c31de6bU, 0x852aef2aU, 0xca6b79edU, 0xd37048acU, 0xf85d1b6fU, 0xe1462a2eU + /* 168 */ , 0x66de36e1U, 0x7fc507a0U, 0x54e85463U, 0x4df36522U, 0x02b2f3e5U, 0x1ba9c2a4U, 0x30849167U, 0x299fa026U + /* 176 */ , 0xe4c5aeb8U, 0xfdde9ff9U, 0xd6f3cc3aU, 0xcfe8fd7bU, 0x80a96bbcU, 0x99b25afdU, 0xb29f093eU, 0xab84387fU + /* 184 */ , 0x2c1c24b0U, 0x350715f1U, 0x1e2a4632U, 0x07317773U, 0x4870e1b4U, 0x516bd0f5U, 0x7a468336U, 0x635db277U + /* 192 */ , 0xcbfad74eU, 0xd2e1e60fU, 0xf9ccb5ccU, 0xe0d7848dU, 0xaf96124aU, 0xb68d230bU, 0x9da070c8U, 0x84bb4189U + /* 200 */ , 0x03235d46U, 0x1a386c07U, 0x31153fc4U, 0x280e0e85U, 0x674f9842U, 0x7e54a903U, 0x5579fac0U, 0x4c62cb81U + /* 208 */ , 0x8138c51fU, 0x9823f45eU, 0xb30ea79dU, 0xaa1596dcU, 0xe554001bU, 0xfc4f315aU, 0xd7626299U, 0xce7953d8U + /* 216 */ , 0x49e14f17U, 0x50fa7e56U, 0x7bd72d95U, 0x62cc1cd4U, 0x2d8d8a13U, 0x3496bb52U, 0x1fbbe891U, 0x06a0d9d0U + /* 224 */ , 0x5e7ef3ecU, 0x4765c2adU, 0x6c48916eU, 0x7553a02fU, 0x3a1236e8U, 0x230907a9U, 0x0824546aU, 0x113f652bU + /* 232 */ , 0x96a779e4U, 0x8fbc48a5U, 0xa4911b66U, 0xbd8a2a27U, 0xf2cbbce0U, 0xebd08da1U, 0xc0fdde62U, 0xd9e6ef23U + /* 240 */ , 0x14bce1bdU, 0x0da7d0fcU, 0x268a833fU, 0x3f91b27eU, 0x70d024b9U, 0x69cb15f8U, 0x42e6463bU, 0x5bfd777aU + /* 248 */ , 0xdc656bb5U, 0xc57e5af4U, 0xee530937U, 0xf7483876U, 0xb809aeb1U, 0xa1129ff0U, 0x8a3fcc33U, 0x9324fd72U + } + , + /* CRC32 table 2 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x01c26a37U, 0x0384d46eU, 0x0246be59U, 0x0709a8dcU, 0x06cbc2ebU, 0x048d7cb2U, 0x054f1685U + /* 8 */ , 0x0e1351b8U, 0x0fd13b8fU, 0x0d9785d6U, 0x0c55efe1U, 0x091af964U, 0x08d89353U, 0x0a9e2d0aU, 0x0b5c473dU + /* 16 */ , 0x1c26a370U, 0x1de4c947U, 0x1fa2771eU, 0x1e601d29U, 0x1b2f0bacU, 0x1aed619bU, 0x18abdfc2U, 0x1969b5f5U + /* 24 */ , 0x1235f2c8U, 0x13f798ffU, 0x11b126a6U, 0x10734c91U, 0x153c5a14U, 0x14fe3023U, 0x16b88e7aU, 0x177ae44dU + /* 32 */ , 0x384d46e0U, 0x398f2cd7U, 0x3bc9928eU, 0x3a0bf8b9U, 0x3f44ee3cU, 0x3e86840bU, 0x3cc03a52U, 0x3d025065U + /* 40 */ , 0x365e1758U, 0x379c7d6fU, 0x35dac336U, 0x3418a901U, 0x3157bf84U, 0x3095d5b3U, 0x32d36beaU, 0x331101ddU + /* 48 */ , 0x246be590U, 0x25a98fa7U, 0x27ef31feU, 0x262d5bc9U, 0x23624d4cU, 0x22a0277bU, 0x20e69922U, 0x2124f315U + /* 56 */ , 0x2a78b428U, 0x2bbade1fU, 0x29fc6046U, 0x283e0a71U, 0x2d711cf4U, 0x2cb376c3U, 0x2ef5c89aU, 0x2f37a2adU + /* 64 */ , 0x709a8dc0U, 0x7158e7f7U, 0x731e59aeU, 0x72dc3399U, 0x7793251cU, 0x76514f2bU, 0x7417f172U, 0x75d59b45U + /* 72 */ , 0x7e89dc78U, 0x7f4bb64fU, 0x7d0d0816U, 0x7ccf6221U, 0x798074a4U, 0x78421e93U, 0x7a04a0caU, 0x7bc6cafdU + /* 80 */ , 0x6cbc2eb0U, 0x6d7e4487U, 0x6f38fadeU, 0x6efa90e9U, 0x6bb5866cU, 0x6a77ec5bU, 0x68315202U, 0x69f33835U + /* 88 */ , 0x62af7f08U, 0x636d153fU, 0x612bab66U, 0x60e9c151U, 0x65a6d7d4U, 0x6464bde3U, 0x662203baU, 0x67e0698dU + /* 96 */ , 0x48d7cb20U, 0x4915a117U, 0x4b531f4eU, 0x4a917579U, 0x4fde63fcU, 0x4e1c09cbU, 0x4c5ab792U, 0x4d98dda5U + /* 104 */ , 0x46c49a98U, 0x4706f0afU, 0x45404ef6U, 0x448224c1U, 0x41cd3244U, 0x400f5873U, 0x4249e62aU, 0x438b8c1dU + /* 112 */ , 0x54f16850U, 0x55330267U, 0x5775bc3eU, 0x56b7d609U, 0x53f8c08cU, 0x523aaabbU, 0x507c14e2U, 0x51be7ed5U + /* 120 */ , 0x5ae239e8U, 0x5b2053dfU, 0x5966ed86U, 0x58a487b1U, 0x5deb9134U, 0x5c29fb03U, 0x5e6f455aU, 0x5fad2f6dU + /* 128 */ , 0xe1351b80U, 0xe0f771b7U, 0xe2b1cfeeU, 0xe373a5d9U, 0xe63cb35cU, 0xe7fed96bU, 0xe5b86732U, 0xe47a0d05U + /* 136 */ , 0xef264a38U, 0xeee4200fU, 0xeca29e56U, 0xed60f461U, 0xe82fe2e4U, 0xe9ed88d3U, 0xebab368aU, 0xea695cbdU + /* 144 */ , 0xfd13b8f0U, 0xfcd1d2c7U, 0xfe976c9eU, 0xff5506a9U, 0xfa1a102cU, 0xfbd87a1bU, 0xf99ec442U, 0xf85cae75U + /* 152 */ , 0xf300e948U, 0xf2c2837fU, 0xf0843d26U, 0xf1465711U, 0xf4094194U, 0xf5cb2ba3U, 0xf78d95faU, 0xf64fffcdU + /* 160 */ , 0xd9785d60U, 0xd8ba3757U, 0xdafc890eU, 0xdb3ee339U, 0xde71f5bcU, 0xdfb39f8bU, 0xddf521d2U, 0xdc374be5U + /* 168 */ , 0xd76b0cd8U, 0xd6a966efU, 0xd4efd8b6U, 0xd52db281U, 0xd062a404U, 0xd1a0ce33U, 0xd3e6706aU, 0xd2241a5dU + /* 176 */ , 0xc55efe10U, 0xc49c9427U, 0xc6da2a7eU, 0xc7184049U, 0xc25756ccU, 0xc3953cfbU, 0xc1d382a2U, 0xc011e895U + /* 184 */ , 0xcb4dafa8U, 0xca8fc59fU, 0xc8c97bc6U, 0xc90b11f1U, 0xcc440774U, 0xcd866d43U, 0xcfc0d31aU, 0xce02b92dU + /* 192 */ , 0x91af9640U, 0x906dfc77U, 0x922b422eU, 0x93e92819U, 0x96a63e9cU, 0x976454abU, 0x9522eaf2U, 0x94e080c5U + /* 200 */ , 0x9fbcc7f8U, 0x9e7eadcfU, 0x9c381396U, 0x9dfa79a1U, 0x98b56f24U, 0x99770513U, 0x9b31bb4aU, 0x9af3d17dU + /* 208 */ , 0x8d893530U, 0x8c4b5f07U, 0x8e0de15eU, 0x8fcf8b69U, 0x8a809decU, 0x8b42f7dbU, 0x89044982U, 0x88c623b5U + /* 216 */ , 0x839a6488U, 0x82580ebfU, 0x801eb0e6U, 0x81dcdad1U, 0x8493cc54U, 0x8551a663U, 0x8717183aU, 0x86d5720dU + /* 224 */ , 0xa9e2d0a0U, 0xa820ba97U, 0xaa6604ceU, 0xaba46ef9U, 0xaeeb787cU, 0xaf29124bU, 0xad6fac12U, 0xacadc625U + /* 232 */ , 0xa7f18118U, 0xa633eb2fU, 0xa4755576U, 0xa5b73f41U, 0xa0f829c4U, 0xa13a43f3U, 0xa37cfdaaU, 0xa2be979dU + /* 240 */ , 0xb5c473d0U, 0xb40619e7U, 0xb640a7beU, 0xb782cd89U, 0xb2cddb0cU, 0xb30fb13bU, 0xb1490f62U, 0xb08b6555U + /* 248 */ , 0xbbd72268U, 0xba15485fU, 0xb853f606U, 0xb9919c31U, 0xbcde8ab4U, 0xbd1ce083U, 0xbf5a5edaU, 0xbe9834edU + } + , + /* CRC32 table 3 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xb8bc6765U, 0xaa09c88bU, 0x12b5afeeU, 0x8f629757U, 0x37def032U, 0x256b5fdcU, 0x9dd738b9U + /* 8 */ , 0xc5b428efU, 0x7d084f8aU, 0x6fbde064U, 0xd7018701U, 0x4ad6bfb8U, 0xf26ad8ddU, 0xe0df7733U, 0x58631056U + /* 16 */ , 0x5019579fU, 0xe8a530faU, 0xfa109f14U, 0x42acf871U, 0xdf7bc0c8U, 0x67c7a7adU, 0x75720843U, 0xcdce6f26U + /* 24 */ , 0x95ad7f70U, 0x2d111815U, 0x3fa4b7fbU, 0x8718d09eU, 0x1acfe827U, 0xa2738f42U, 0xb0c620acU, 0x087a47c9U + /* 32 */ , 0xa032af3eU, 0x188ec85bU, 0x0a3b67b5U, 0xb28700d0U, 0x2f503869U, 0x97ec5f0cU, 0x8559f0e2U, 0x3de59787U + /* 40 */ , 0x658687d1U, 0xdd3ae0b4U, 0xcf8f4f5aU, 0x7733283fU, 0xeae41086U, 0x525877e3U, 0x40edd80dU, 0xf851bf68U + /* 48 */ , 0xf02bf8a1U, 0x48979fc4U, 0x5a22302aU, 0xe29e574fU, 0x7f496ff6U, 0xc7f50893U, 0xd540a77dU, 0x6dfcc018U + /* 56 */ , 0x359fd04eU, 0x8d23b72bU, 0x9f9618c5U, 0x272a7fa0U, 0xbafd4719U, 0x0241207cU, 0x10f48f92U, 0xa848e8f7U + /* 64 */ , 0x9b14583dU, 0x23a83f58U, 0x311d90b6U, 0x89a1f7d3U, 0x1476cf6aU, 0xaccaa80fU, 0xbe7f07e1U, 0x06c36084U + /* 72 */ , 0x5ea070d2U, 0xe61c17b7U, 0xf4a9b859U, 0x4c15df3cU, 0xd1c2e785U, 0x697e80e0U, 0x7bcb2f0eU, 0xc377486bU + /* 80 */ , 0xcb0d0fa2U, 0x73b168c7U, 0x6104c729U, 0xd9b8a04cU, 0x446f98f5U, 0xfcd3ff90U, 0xee66507eU, 0x56da371bU + /* 88 */ , 0x0eb9274dU, 0xb6054028U, 0xa4b0efc6U, 0x1c0c88a3U, 0x81dbb01aU, 0x3967d77fU, 0x2bd27891U, 0x936e1ff4U + /* 96 */ , 0x3b26f703U, 0x839a9066U, 0x912f3f88U, 0x299358edU, 0xb4446054U, 0x0cf80731U, 0x1e4da8dfU, 0xa6f1cfbaU + /* 104 */ , 0xfe92dfecU, 0x462eb889U, 0x549b1767U, 0xec277002U, 0x71f048bbU, 0xc94c2fdeU, 0xdbf98030U, 0x6345e755U + /* 112 */ , 0x6b3fa09cU, 0xd383c7f9U, 0xc1366817U, 0x798a0f72U, 0xe45d37cbU, 0x5ce150aeU, 0x4e54ff40U, 0xf6e89825U + /* 120 */ , 0xae8b8873U, 0x1637ef16U, 0x048240f8U, 0xbc3e279dU, 0x21e91f24U, 0x99557841U, 0x8be0d7afU, 0x335cb0caU + /* 128 */ , 0xed59b63bU, 0x55e5d15eU, 0x47507eb0U, 0xffec19d5U, 0x623b216cU, 0xda874609U, 0xc832e9e7U, 0x708e8e82U + /* 136 */ , 0x28ed9ed4U, 0x9051f9b1U, 0x82e4565fU, 0x3a58313aU, 0xa78f0983U, 0x1f336ee6U, 0x0d86c108U, 0xb53aa66dU + /* 144 */ , 0xbd40e1a4U, 0x05fc86c1U, 0x1749292fU, 0xaff54e4aU, 0x322276f3U, 0x8a9e1196U, 0x982bbe78U, 0x2097d91dU + /* 152 */ , 0x78f4c94bU, 0xc048ae2eU, 0xd2fd01c0U, 0x6a4166a5U, 0xf7965e1cU, 0x4f2a3979U, 0x5d9f9697U, 0xe523f1f2U + /* 160 */ , 0x4d6b1905U, 0xf5d77e60U, 0xe762d18eU, 0x5fdeb6ebU, 0xc2098e52U, 0x7ab5e937U, 0x680046d9U, 0xd0bc21bcU + /* 168 */ , 0x88df31eaU, 0x3063568fU, 0x22d6f961U, 0x9a6a9e04U, 0x07bda6bdU, 0xbf01c1d8U, 0xadb46e36U, 0x15080953U + /* 176 */ , 0x1d724e9aU, 0xa5ce29ffU, 0xb77b8611U, 0x0fc7e174U, 0x9210d9cdU, 0x2aacbea8U, 0x38191146U, 0x80a57623U + /* 184 */ , 0xd8c66675U, 0x607a0110U, 0x72cfaefeU, 0xca73c99bU, 0x57a4f122U, 0xef189647U, 0xfdad39a9U, 0x45115eccU + /* 192 */ , 0x764dee06U, 0xcef18963U, 0xdc44268dU, 0x64f841e8U, 0xf92f7951U, 0x41931e34U, 0x5326b1daU, 0xeb9ad6bfU + /* 200 */ , 0xb3f9c6e9U, 0x0b45a18cU, 0x19f00e62U, 0xa14c6907U, 0x3c9b51beU, 0x842736dbU, 0x96929935U, 0x2e2efe50U + /* 208 */ , 0x2654b999U, 0x9ee8defcU, 0x8c5d7112U, 0x34e11677U, 0xa9362eceU, 0x118a49abU, 0x033fe645U, 0xbb838120U + /* 216 */ , 0xe3e09176U, 0x5b5cf613U, 0x49e959fdU, 0xf1553e98U, 0x6c820621U, 0xd43e6144U, 0xc68bceaaU, 0x7e37a9cfU + /* 224 */ , 0xd67f4138U, 0x6ec3265dU, 0x7c7689b3U, 0xc4caeed6U, 0x591dd66fU, 0xe1a1b10aU, 0xf3141ee4U, 0x4ba87981U + /* 232 */ , 0x13cb69d7U, 0xab770eb2U, 0xb9c2a15cU, 0x017ec639U, 0x9ca9fe80U, 0x241599e5U, 0x36a0360bU, 0x8e1c516eU + /* 240 */ , 0x866616a7U, 0x3eda71c2U, 0x2c6fde2cU, 0x94d3b949U, 0x090481f0U, 0xb1b8e695U, 0xa30d497bU, 0x1bb12e1eU + /* 248 */ , 0x43d23e48U, 0xfb6e592dU, 0xe9dbf6c3U, 0x516791a6U, 0xccb0a91fU, 0x740cce7aU, 0x66b96194U, 0xde0506f1U + } + , + /* CRC32 table 4 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x96300777U, 0x2c610eeeU, 0xba510999U, 0x19c46d07U, 0x8ff46a70U, 0x35a563e9U, 0xa395649eU + /* 8 */ , 0x3288db0eU, 0xa4b8dc79U, 0x1ee9d5e0U, 0x88d9d297U, 0x2b4cb609U, 0xbd7cb17eU, 0x072db8e7U, 0x911dbf90U + /* 16 */ , 0x6410b71dU, 0xf220b06aU, 0x4871b9f3U, 0xde41be84U, 0x7dd4da1aU, 0xebe4dd6dU, 0x51b5d4f4U, 0xc785d383U + /* 24 */ , 0x56986c13U, 0xc0a86b64U, 0x7af962fdU, 0xecc9658aU, 0x4f5c0114U, 0xd96c0663U, 0x633d0ffaU, 0xf50d088dU + /* 32 */ , 0xc8206e3bU, 0x5e10694cU, 0xe44160d5U, 0x727167a2U, 0xd1e4033cU, 0x47d4044bU, 0xfd850dd2U, 0x6bb50aa5U + /* 40 */ , 0xfaa8b535U, 0x6c98b242U, 0xd6c9bbdbU, 0x40f9bcacU, 0xe36cd832U, 0x755cdf45U, 0xcf0dd6dcU, 0x593dd1abU + /* 48 */ , 0xac30d926U, 0x3a00de51U, 0x8051d7c8U, 0x1661d0bfU, 0xb5f4b421U, 0x23c4b356U, 0x9995bacfU, 0x0fa5bdb8U + /* 56 */ , 0x9eb80228U, 0x0888055fU, 0xb2d90cc6U, 0x24e90bb1U, 0x877c6f2fU, 0x114c6858U, 0xab1d61c1U, 0x3d2d66b6U + /* 64 */ , 0x9041dc76U, 0x0671db01U, 0xbc20d298U, 0x2a10d5efU, 0x8985b171U, 0x1fb5b606U, 0xa5e4bf9fU, 0x33d4b8e8U + /* 72 */ , 0xa2c90778U, 0x34f9000fU, 0x8ea80996U, 0x18980ee1U, 0xbb0d6a7fU, 0x2d3d6d08U, 0x976c6491U, 0x015c63e6U + /* 80 */ , 0xf4516b6bU, 0x62616c1cU, 0xd8306585U, 0x4e0062f2U, 0xed95066cU, 0x7ba5011bU, 0xc1f40882U, 0x57c40ff5U + /* 88 */ , 0xc6d9b065U, 0x50e9b712U, 0xeab8be8bU, 0x7c88b9fcU, 0xdf1ddd62U, 0x492dda15U, 0xf37cd38cU, 0x654cd4fbU + /* 96 */ , 0x5861b24dU, 0xce51b53aU, 0x7400bca3U, 0xe230bbd4U, 0x41a5df4aU, 0xd795d83dU, 0x6dc4d1a4U, 0xfbf4d6d3U + /* 104 */ , 0x6ae96943U, 0xfcd96e34U, 0x468867adU, 0xd0b860daU, 0x732d0444U, 0xe51d0333U, 0x5f4c0aaaU, 0xc97c0dddU + /* 112 */ , 0x3c710550U, 0xaa410227U, 0x10100bbeU, 0x86200cc9U, 0x25b56857U, 0xb3856f20U, 0x09d466b9U, 0x9fe461ceU + /* 120 */ , 0x0ef9de5eU, 0x98c9d929U, 0x2298d0b0U, 0xb4a8d7c7U, 0x173db359U, 0x810db42eU, 0x3b5cbdb7U, 0xad6cbac0U + /* 128 */ , 0x2083b8edU, 0xb6b3bf9aU, 0x0ce2b603U, 0x9ad2b174U, 0x3947d5eaU, 0xaf77d29dU, 0x1526db04U, 0x8316dc73U + /* 136 */ , 0x120b63e3U, 0x843b6494U, 0x3e6a6d0dU, 0xa85a6a7aU, 0x0bcf0ee4U, 0x9dff0993U, 0x27ae000aU, 0xb19e077dU + /* 144 */ , 0x44930ff0U, 0xd2a30887U, 0x68f2011eU, 0xfec20669U, 0x5d5762f7U, 0xcb676580U, 0x71366c19U, 0xe7066b6eU + /* 152 */ , 0x761bd4feU, 0xe02bd389U, 0x5a7ada10U, 0xcc4add67U, 0x6fdfb9f9U, 0xf9efbe8eU, 0x43beb717U, 0xd58eb060U + /* 160 */ , 0xe8a3d6d6U, 0x7e93d1a1U, 0xc4c2d838U, 0x52f2df4fU, 0xf167bbd1U, 0x6757bca6U, 0xdd06b53fU, 0x4b36b248U + /* 168 */ , 0xda2b0dd8U, 0x4c1b0aafU, 0xf64a0336U, 0x607a0441U, 0xc3ef60dfU, 0x55df67a8U, 0xef8e6e31U, 0x79be6946U + /* 176 */ , 0x8cb361cbU, 0x1a8366bcU, 0xa0d26f25U, 0x36e26852U, 0x95770cccU, 0x03470bbbU, 0xb9160222U, 0x2f260555U + /* 184 */ , 0xbe3bbac5U, 0x280bbdb2U, 0x925ab42bU, 0x046ab35cU, 0xa7ffd7c2U, 0x31cfd0b5U, 0x8b9ed92cU, 0x1daede5bU + /* 192 */ , 0xb0c2649bU, 0x26f263ecU, 0x9ca36a75U, 0x0a936d02U, 0xa906099cU, 0x3f360eebU, 0x85670772U, 0x13570005U + /* 200 */ , 0x824abf95U, 0x147ab8e2U, 0xae2bb17bU, 0x381bb60cU, 0x9b8ed292U, 0x0dbed5e5U, 0xb7efdc7cU, 0x21dfdb0bU + /* 208 */ , 0xd4d2d386U, 0x42e2d4f1U, 0xf8b3dd68U, 0x6e83da1fU, 0xcd16be81U, 0x5b26b9f6U, 0xe177b06fU, 0x7747b718U + /* 216 */ , 0xe65a0888U, 0x706a0fffU, 0xca3b0666U, 0x5c0b0111U, 0xff9e658fU, 0x69ae62f8U, 0xd3ff6b61U, 0x45cf6c16U + /* 224 */ , 0x78e20aa0U, 0xeed20dd7U, 0x5483044eU, 0xc2b30339U, 0x612667a7U, 0xf71660d0U, 0x4d476949U, 0xdb776e3eU + /* 232 */ , 0x4a6ad1aeU, 0xdc5ad6d9U, 0x660bdf40U, 0xf03bd837U, 0x53aebca9U, 0xc59ebbdeU, 0x7fcfb247U, 0xe9ffb530U + /* 240 */ , 0x1cf2bdbdU, 0x8ac2bacaU, 0x3093b353U, 0xa6a3b424U, 0x0536d0baU, 0x9306d7cdU, 0x2957de54U, 0xbf67d923U + /* 248 */ , 0x2e7a66b3U, 0xb84a61c4U, 0x021b685dU, 0x942b6f2aU, 0x37be0bb4U, 0xa18e0cc3U, 0x1bdf055aU, 0x8def022dU + } + , + /* CRC32 table 5 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x41311b19U, 0x82623632U, 0xc3532d2bU, 0x04c56c64U, 0x45f4777dU, 0x86a75a56U, 0xc796414fU + /* 8 */ , 0x088ad9c8U, 0x49bbc2d1U, 0x8ae8effaU, 0xcbd9f4e3U, 0x0c4fb5acU, 0x4d7eaeb5U, 0x8e2d839eU, 0xcf1c9887U + /* 16 */ , 0x5112c24aU, 0x1023d953U, 0xd370f478U, 0x9241ef61U, 0x55d7ae2eU, 0x14e6b537U, 0xd7b5981cU, 0x96848305U + /* 24 */ , 0x59981b82U, 0x18a9009bU, 0xdbfa2db0U, 0x9acb36a9U, 0x5d5d77e6U, 0x1c6c6cffU, 0xdf3f41d4U, 0x9e0e5acdU + /* 32 */ , 0xa2248495U, 0xe3159f8cU, 0x2046b2a7U, 0x6177a9beU, 0xa6e1e8f1U, 0xe7d0f3e8U, 0x2483dec3U, 0x65b2c5daU + /* 40 */ , 0xaaae5d5dU, 0xeb9f4644U, 0x28cc6b6fU, 0x69fd7076U, 0xae6b3139U, 0xef5a2a20U, 0x2c09070bU, 0x6d381c12U + /* 48 */ , 0xf33646dfU, 0xb2075dc6U, 0x715470edU, 0x30656bf4U, 0xf7f32abbU, 0xb6c231a2U, 0x75911c89U, 0x34a00790U + /* 56 */ , 0xfbbc9f17U, 0xba8d840eU, 0x79dea925U, 0x38efb23cU, 0xff79f373U, 0xbe48e86aU, 0x7d1bc541U, 0x3c2ade58U + /* 64 */ , 0x054f79f0U, 0x447e62e9U, 0x872d4fc2U, 0xc61c54dbU, 0x018a1594U, 0x40bb0e8dU, 0x83e823a6U, 0xc2d938bfU + /* 72 */ , 0x0dc5a038U, 0x4cf4bb21U, 0x8fa7960aU, 0xce968d13U, 0x0900cc5cU, 0x4831d745U, 0x8b62fa6eU, 0xca53e177U + /* 80 */ , 0x545dbbbaU, 0x156ca0a3U, 0xd63f8d88U, 0x970e9691U, 0x5098d7deU, 0x11a9ccc7U, 0xd2fae1ecU, 0x93cbfaf5U + /* 88 */ , 0x5cd76272U, 0x1de6796bU, 0xdeb55440U, 0x9f844f59U, 0x58120e16U, 0x1923150fU, 0xda703824U, 0x9b41233dU + /* 96 */ , 0xa76bfd65U, 0xe65ae67cU, 0x2509cb57U, 0x6438d04eU, 0xa3ae9101U, 0xe29f8a18U, 0x21cca733U, 0x60fdbc2aU + /* 104 */ , 0xafe124adU, 0xeed03fb4U, 0x2d83129fU, 0x6cb20986U, 0xab2448c9U, 0xea1553d0U, 0x29467efbU, 0x687765e2U + /* 112 */ , 0xf6793f2fU, 0xb7482436U, 0x741b091dU, 0x352a1204U, 0xf2bc534bU, 0xb38d4852U, 0x70de6579U, 0x31ef7e60U + /* 120 */ , 0xfef3e6e7U, 0xbfc2fdfeU, 0x7c91d0d5U, 0x3da0cbccU, 0xfa368a83U, 0xbb07919aU, 0x7854bcb1U, 0x3965a7a8U + /* 128 */ , 0x4b98833bU, 0x0aa99822U, 0xc9fab509U, 0x88cbae10U, 0x4f5def5fU, 0x0e6cf446U, 0xcd3fd96dU, 0x8c0ec274U + /* 136 */ , 0x43125af3U, 0x022341eaU, 0xc1706cc1U, 0x804177d8U, 0x47d73697U, 0x06e62d8eU, 0xc5b500a5U, 0x84841bbcU + /* 144 */ , 0x1a8a4171U, 0x5bbb5a68U, 0x98e87743U, 0xd9d96c5aU, 0x1e4f2d15U, 0x5f7e360cU, 0x9c2d1b27U, 0xdd1c003eU + /* 152 */ , 0x120098b9U, 0x533183a0U, 0x9062ae8bU, 0xd153b592U, 0x16c5f4ddU, 0x57f4efc4U, 0x94a7c2efU, 0xd596d9f6U + /* 160 */ , 0xe9bc07aeU, 0xa88d1cb7U, 0x6bde319cU, 0x2aef2a85U, 0xed796bcaU, 0xac4870d3U, 0x6f1b5df8U, 0x2e2a46e1U + /* 168 */ , 0xe136de66U, 0xa007c57fU, 0x6354e854U, 0x2265f34dU, 0xe5f3b202U, 0xa4c2a91bU, 0x67918430U, 0x26a09f29U + /* 176 */ , 0xb8aec5e4U, 0xf99fdefdU, 0x3accf3d6U, 0x7bfde8cfU, 0xbc6ba980U, 0xfd5ab299U, 0x3e099fb2U, 0x7f3884abU + /* 184 */ , 0xb0241c2cU, 0xf1150735U, 0x32462a1eU, 0x73773107U, 0xb4e17048U, 0xf5d06b51U, 0x3683467aU, 0x77b25d63U + /* 192 */ , 0x4ed7facbU, 0x0fe6e1d2U, 0xccb5ccf9U, 0x8d84d7e0U, 0x4a1296afU, 0x0b238db6U, 0xc870a09dU, 0x8941bb84U + /* 200 */ , 0x465d2303U, 0x076c381aU, 0xc43f1531U, 0x850e0e28U, 0x42984f67U, 0x03a9547eU, 0xc0fa7955U, 0x81cb624cU + /* 208 */ , 0x1fc53881U, 0x5ef42398U, 0x9da70eb3U, 0xdc9615aaU, 0x1b0054e5U, 0x5a314ffcU, 0x996262d7U, 0xd85379ceU + /* 216 */ , 0x174fe149U, 0x567efa50U, 0x952dd77bU, 0xd41ccc62U, 0x138a8d2dU, 0x52bb9634U, 0x91e8bb1fU, 0xd0d9a006U + /* 224 */ , 0xecf37e5eU, 0xadc26547U, 0x6e91486cU, 0x2fa05375U, 0xe836123aU, 0xa9070923U, 0x6a542408U, 0x2b653f11U + /* 232 */ , 0xe479a796U, 0xa548bc8fU, 0x661b91a4U, 0x272a8abdU, 0xe0bccbf2U, 0xa18dd0ebU, 0x62defdc0U, 0x23efe6d9U + /* 240 */ , 0xbde1bc14U, 0xfcd0a70dU, 0x3f838a26U, 0x7eb2913fU, 0xb924d070U, 0xf815cb69U, 0x3b46e642U, 0x7a77fd5bU + /* 248 */ , 0xb56b65dcU, 0xf45a7ec5U, 0x370953eeU, 0x763848f7U, 0xb1ae09b8U, 0xf09f12a1U, 0x33cc3f8aU, 0x72fd2493U + } + , + /* CRC32 table 6 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x376ac201U, 0x6ed48403U, 0x59be4602U, 0xdca80907U, 0xebc2cb06U, 0xb27c8d04U, 0x85164f05U + /* 8 */ , 0xb851130eU, 0x8f3bd10fU, 0xd685970dU, 0xe1ef550cU, 0x64f91a09U, 0x5393d808U, 0x0a2d9e0aU, 0x3d475c0bU + /* 16 */ , 0x70a3261cU, 0x47c9e41dU, 0x1e77a21fU, 0x291d601eU, 0xac0b2f1bU, 0x9b61ed1aU, 0xc2dfab18U, 0xf5b56919U + /* 24 */ , 0xc8f23512U, 0xff98f713U, 0xa626b111U, 0x914c7310U, 0x145a3c15U, 0x2330fe14U, 0x7a8eb816U, 0x4de47a17U + /* 32 */ , 0xe0464d38U, 0xd72c8f39U, 0x8e92c93bU, 0xb9f80b3aU, 0x3cee443fU, 0x0b84863eU, 0x523ac03cU, 0x6550023dU + /* 40 */ , 0x58175e36U, 0x6f7d9c37U, 0x36c3da35U, 0x01a91834U, 0x84bf5731U, 0xb3d59530U, 0xea6bd332U, 0xdd011133U + /* 48 */ , 0x90e56b24U, 0xa78fa925U, 0xfe31ef27U, 0xc95b2d26U, 0x4c4d6223U, 0x7b27a022U, 0x2299e620U, 0x15f32421U + /* 56 */ , 0x28b4782aU, 0x1fdeba2bU, 0x4660fc29U, 0x710a3e28U, 0xf41c712dU, 0xc376b32cU, 0x9ac8f52eU, 0xada2372fU + /* 64 */ , 0xc08d9a70U, 0xf7e75871U, 0xae591e73U, 0x9933dc72U, 0x1c259377U, 0x2b4f5176U, 0x72f11774U, 0x459bd575U + /* 72 */ , 0x78dc897eU, 0x4fb64b7fU, 0x16080d7dU, 0x2162cf7cU, 0xa4748079U, 0x931e4278U, 0xcaa0047aU, 0xfdcac67bU + /* 80 */ , 0xb02ebc6cU, 0x87447e6dU, 0xdefa386fU, 0xe990fa6eU, 0x6c86b56bU, 0x5bec776aU, 0x02523168U, 0x3538f369U + /* 88 */ , 0x087faf62U, 0x3f156d63U, 0x66ab2b61U, 0x51c1e960U, 0xd4d7a665U, 0xe3bd6464U, 0xba032266U, 0x8d69e067U + /* 96 */ , 0x20cbd748U, 0x17a11549U, 0x4e1f534bU, 0x7975914aU, 0xfc63de4fU, 0xcb091c4eU, 0x92b75a4cU, 0xa5dd984dU + /* 104 */ , 0x989ac446U, 0xaff00647U, 0xf64e4045U, 0xc1248244U, 0x4432cd41U, 0x73580f40U, 0x2ae64942U, 0x1d8c8b43U + /* 112 */ , 0x5068f154U, 0x67023355U, 0x3ebc7557U, 0x09d6b756U, 0x8cc0f853U, 0xbbaa3a52U, 0xe2147c50U, 0xd57ebe51U + /* 120 */ , 0xe839e25aU, 0xdf53205bU, 0x86ed6659U, 0xb187a458U, 0x3491eb5dU, 0x03fb295cU, 0x5a456f5eU, 0x6d2fad5fU + /* 128 */ , 0x801b35e1U, 0xb771f7e0U, 0xeecfb1e2U, 0xd9a573e3U, 0x5cb33ce6U, 0x6bd9fee7U, 0x3267b8e5U, 0x050d7ae4U + /* 136 */ , 0x384a26efU, 0x0f20e4eeU, 0x569ea2ecU, 0x61f460edU, 0xe4e22fe8U, 0xd388ede9U, 0x8a36abebU, 0xbd5c69eaU + /* 144 */ , 0xf0b813fdU, 0xc7d2d1fcU, 0x9e6c97feU, 0xa90655ffU, 0x2c101afaU, 0x1b7ad8fbU, 0x42c49ef9U, 0x75ae5cf8U + /* 152 */ , 0x48e900f3U, 0x7f83c2f2U, 0x263d84f0U, 0x115746f1U, 0x944109f4U, 0xa32bcbf5U, 0xfa958df7U, 0xcdff4ff6U + /* 160 */ , 0x605d78d9U, 0x5737bad8U, 0x0e89fcdaU, 0x39e33edbU, 0xbcf571deU, 0x8b9fb3dfU, 0xd221f5ddU, 0xe54b37dcU + /* 168 */ , 0xd80c6bd7U, 0xef66a9d6U, 0xb6d8efd4U, 0x81b22dd5U, 0x04a462d0U, 0x33cea0d1U, 0x6a70e6d3U, 0x5d1a24d2U + /* 176 */ , 0x10fe5ec5U, 0x27949cc4U, 0x7e2adac6U, 0x494018c7U, 0xcc5657c2U, 0xfb3c95c3U, 0xa282d3c1U, 0x95e811c0U + /* 184 */ , 0xa8af4dcbU, 0x9fc58fcaU, 0xc67bc9c8U, 0xf1110bc9U, 0x740744ccU, 0x436d86cdU, 0x1ad3c0cfU, 0x2db902ceU + /* 192 */ , 0x4096af91U, 0x77fc6d90U, 0x2e422b92U, 0x1928e993U, 0x9c3ea696U, 0xab546497U, 0xf2ea2295U, 0xc580e094U + /* 200 */ , 0xf8c7bc9fU, 0xcfad7e9eU, 0x9613389cU, 0xa179fa9dU, 0x246fb598U, 0x13057799U, 0x4abb319bU, 0x7dd1f39aU + /* 208 */ , 0x3035898dU, 0x075f4b8cU, 0x5ee10d8eU, 0x698bcf8fU, 0xec9d808aU, 0xdbf7428bU, 0x82490489U, 0xb523c688U + /* 216 */ , 0x88649a83U, 0xbf0e5882U, 0xe6b01e80U, 0xd1dadc81U, 0x54cc9384U, 0x63a65185U, 0x3a181787U, 0x0d72d586U + /* 224 */ , 0xa0d0e2a9U, 0x97ba20a8U, 0xce0466aaU, 0xf96ea4abU, 0x7c78ebaeU, 0x4b1229afU, 0x12ac6fadU, 0x25c6adacU + /* 232 */ , 0x1881f1a7U, 0x2feb33a6U, 0x765575a4U, 0x413fb7a5U, 0xc429f8a0U, 0xf3433aa1U, 0xaafd7ca3U, 0x9d97bea2U + /* 240 */ , 0xd073c4b5U, 0xe71906b4U, 0xbea740b6U, 0x89cd82b7U, 0x0cdbcdb2U, 0x3bb10fb3U, 0x620f49b1U, 0x55658bb0U + /* 248 */ , 0x6822d7bbU, 0x5f4815baU, 0x06f653b8U, 0x319c91b9U, 0xb48adebcU, 0x83e01cbdU, 0xda5e5abfU, 0xed3498beU + } + , + /* CRC32 table 7 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x6567bcb8U, 0x8bc809aaU, 0xeeafb512U, 0x5797628fU, 0x32f0de37U, 0xdc5f6b25U, 0xb938d79dU + /* 8 */ , 0xef28b4c5U, 0x8a4f087dU, 0x64e0bd6fU, 0x018701d7U, 0xb8bfd64aU, 0xddd86af2U, 0x3377dfe0U, 0x56106358U + /* 16 */ , 0x9f571950U, 0xfa30a5e8U, 0x149f10faU, 0x71f8ac42U, 0xc8c07bdfU, 0xada7c767U, 0x43087275U, 0x266fcecdU + /* 24 */ , 0x707fad95U, 0x1518112dU, 0xfbb7a43fU, 0x9ed01887U, 0x27e8cf1aU, 0x428f73a2U, 0xac20c6b0U, 0xc9477a08U + /* 32 */ , 0x3eaf32a0U, 0x5bc88e18U, 0xb5673b0aU, 0xd00087b2U, 0x6938502fU, 0x0c5fec97U, 0xe2f05985U, 0x8797e53dU + /* 40 */ , 0xd1878665U, 0xb4e03addU, 0x5a4f8fcfU, 0x3f283377U, 0x8610e4eaU, 0xe3775852U, 0x0dd8ed40U, 0x68bf51f8U + /* 48 */ , 0xa1f82bf0U, 0xc49f9748U, 0x2a30225aU, 0x4f579ee2U, 0xf66f497fU, 0x9308f5c7U, 0x7da740d5U, 0x18c0fc6dU + /* 56 */ , 0x4ed09f35U, 0x2bb7238dU, 0xc518969fU, 0xa07f2a27U, 0x1947fdbaU, 0x7c204102U, 0x928ff410U, 0xf7e848a8U + /* 64 */ , 0x3d58149bU, 0x583fa823U, 0xb6901d31U, 0xd3f7a189U, 0x6acf7614U, 0x0fa8caacU, 0xe1077fbeU, 0x8460c306U + /* 72 */ , 0xd270a05eU, 0xb7171ce6U, 0x59b8a9f4U, 0x3cdf154cU, 0x85e7c2d1U, 0xe0807e69U, 0x0e2fcb7bU, 0x6b4877c3U + /* 80 */ , 0xa20f0dcbU, 0xc768b173U, 0x29c70461U, 0x4ca0b8d9U, 0xf5986f44U, 0x90ffd3fcU, 0x7e5066eeU, 0x1b37da56U + /* 88 */ , 0x4d27b90eU, 0x284005b6U, 0xc6efb0a4U, 0xa3880c1cU, 0x1ab0db81U, 0x7fd76739U, 0x9178d22bU, 0xf41f6e93U + /* 96 */ , 0x03f7263bU, 0x66909a83U, 0x883f2f91U, 0xed589329U, 0x546044b4U, 0x3107f80cU, 0xdfa84d1eU, 0xbacff1a6U + /* 104 */ , 0xecdf92feU, 0x89b82e46U, 0x67179b54U, 0x027027ecU, 0xbb48f071U, 0xde2f4cc9U, 0x3080f9dbU, 0x55e74563U + /* 112 */ , 0x9ca03f6bU, 0xf9c783d3U, 0x176836c1U, 0x720f8a79U, 0xcb375de4U, 0xae50e15cU, 0x40ff544eU, 0x2598e8f6U + /* 120 */ , 0x73888baeU, 0x16ef3716U, 0xf8408204U, 0x9d273ebcU, 0x241fe921U, 0x41785599U, 0xafd7e08bU, 0xcab05c33U + /* 128 */ , 0x3bb659edU, 0x5ed1e555U, 0xb07e5047U, 0xd519ecffU, 0x6c213b62U, 0x094687daU, 0xe7e932c8U, 0x828e8e70U + /* 136 */ , 0xd49eed28U, 0xb1f95190U, 0x5f56e482U, 0x3a31583aU, 0x83098fa7U, 0xe66e331fU, 0x08c1860dU, 0x6da63ab5U + /* 144 */ , 0xa4e140bdU, 0xc186fc05U, 0x2f294917U, 0x4a4ef5afU, 0xf3762232U, 0x96119e8aU, 0x78be2b98U, 0x1dd99720U + /* 152 */ , 0x4bc9f478U, 0x2eae48c0U, 0xc001fdd2U, 0xa566416aU, 0x1c5e96f7U, 0x79392a4fU, 0x97969f5dU, 0xf2f123e5U + /* 160 */ , 0x05196b4dU, 0x607ed7f5U, 0x8ed162e7U, 0xebb6de5fU, 0x528e09c2U, 0x37e9b57aU, 0xd9460068U, 0xbc21bcd0U + /* 168 */ , 0xea31df88U, 0x8f566330U, 0x61f9d622U, 0x049e6a9aU, 0xbda6bd07U, 0xd8c101bfU, 0x366eb4adU, 0x53090815U + /* 176 */ , 0x9a4e721dU, 0xff29cea5U, 0x11867bb7U, 0x74e1c70fU, 0xcdd91092U, 0xa8beac2aU, 0x46111938U, 0x2376a580U + /* 184 */ , 0x7566c6d8U, 0x10017a60U, 0xfeaecf72U, 0x9bc973caU, 0x22f1a457U, 0x479618efU, 0xa939adfdU, 0xcc5e1145U + /* 192 */ , 0x06ee4d76U, 0x6389f1ceU, 0x8d2644dcU, 0xe841f864U, 0x51792ff9U, 0x341e9341U, 0xdab12653U, 0xbfd69aebU + /* 200 */ , 0xe9c6f9b3U, 0x8ca1450bU, 0x620ef019U, 0x07694ca1U, 0xbe519b3cU, 0xdb362784U, 0x35999296U, 0x50fe2e2eU + /* 208 */ , 0x99b95426U, 0xfcdee89eU, 0x12715d8cU, 0x7716e134U, 0xce2e36a9U, 0xab498a11U, 0x45e63f03U, 0x208183bbU + /* 216 */ , 0x7691e0e3U, 0x13f65c5bU, 0xfd59e949U, 0x983e55f1U, 0x2106826cU, 0x44613ed4U, 0xaace8bc6U, 0xcfa9377eU + /* 224 */ , 0x38417fd6U, 0x5d26c36eU, 0xb389767cU, 0xd6eecac4U, 0x6fd61d59U, 0x0ab1a1e1U, 0xe41e14f3U, 0x8179a84bU + /* 232 */ , 0xd769cb13U, 0xb20e77abU, 0x5ca1c2b9U, 0x39c67e01U, 0x80fea99cU, 0xe5991524U, 0x0b36a036U, 0x6e511c8eU + /* 240 */ , 0xa7166686U, 0xc271da3eU, 0x2cde6f2cU, 0x49b9d394U, 0xf0810409U, 0x95e6b8b1U, 0x7b490da3U, 0x1e2eb11bU + /* 248 */ , 0x483ed243U, 0x2d596efbU, 0xc3f6dbe9U, 0xa6916751U, 0x1fa9b0ccU, 0x7ace0c74U, 0x9461b966U, 0xf10605deU + } + #endif + }; + +juint StubRoutines::ppc64::_crc32c_table[CRC32_TABLES][CRC32_COLUMN_SIZE] = { + /* polyBits = 4394350321 0x0000000105ec76f1L, shifted = 0x82f63b78 */ + /* CRC32C table for single bytes, auto-generated. DO NOT MODIFY! */ + /* CRC32C table 0 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xf26b8303U, 0xe13b70f7U, 0x1350f3f4U, 0xc79a971fU, 0x35f1141cU, 0x26a1e7e8U, 0xd4ca64ebU + /* 8 */ , 0x8ad958cfU, 0x78b2dbccU, 0x6be22838U, 0x9989ab3bU, 0x4d43cfd0U, 0xbf284cd3U, 0xac78bf27U, 0x5e133c24U + /* 16 */ , 0x105ec76fU, 0xe235446cU, 0xf165b798U, 0x030e349bU, 0xd7c45070U, 0x25afd373U, 0x36ff2087U, 0xc494a384U + /* 24 */ , 0x9a879fa0U, 0x68ec1ca3U, 0x7bbcef57U, 0x89d76c54U, 0x5d1d08bfU, 0xaf768bbcU, 0xbc267848U, 0x4e4dfb4bU + /* 32 */ , 0x20bd8edeU, 0xd2d60dddU, 0xc186fe29U, 0x33ed7d2aU, 0xe72719c1U, 0x154c9ac2U, 0x061c6936U, 0xf477ea35U + /* 40 */ , 0xaa64d611U, 0x580f5512U, 0x4b5fa6e6U, 0xb93425e5U, 0x6dfe410eU, 0x9f95c20dU, 0x8cc531f9U, 0x7eaeb2faU + /* 48 */ , 0x30e349b1U, 0xc288cab2U, 0xd1d83946U, 0x23b3ba45U, 0xf779deaeU, 0x05125dadU, 0x1642ae59U, 0xe4292d5aU + /* 56 */ , 0xba3a117eU, 0x4851927dU, 0x5b016189U, 0xa96ae28aU, 0x7da08661U, 0x8fcb0562U, 0x9c9bf696U, 0x6ef07595U + /* 64 */ , 0x417b1dbcU, 0xb3109ebfU, 0xa0406d4bU, 0x522bee48U, 0x86e18aa3U, 0x748a09a0U, 0x67dafa54U, 0x95b17957U + /* 72 */ , 0xcba24573U, 0x39c9c670U, 0x2a993584U, 0xd8f2b687U, 0x0c38d26cU, 0xfe53516fU, 0xed03a29bU, 0x1f682198U + /* 80 */ , 0x5125dad3U, 0xa34e59d0U, 0xb01eaa24U, 0x42752927U, 0x96bf4dccU, 0x64d4cecfU, 0x77843d3bU, 0x85efbe38U + /* 88 */ , 0xdbfc821cU, 0x2997011fU, 0x3ac7f2ebU, 0xc8ac71e8U, 0x1c661503U, 0xee0d9600U, 0xfd5d65f4U, 0x0f36e6f7U + /* 96 */ , 0x61c69362U, 0x93ad1061U, 0x80fde395U, 0x72966096U, 0xa65c047dU, 0x5437877eU, 0x4767748aU, 0xb50cf789U + /* 104 */ , 0xeb1fcbadU, 0x197448aeU, 0x0a24bb5aU, 0xf84f3859U, 0x2c855cb2U, 0xdeeedfb1U, 0xcdbe2c45U, 0x3fd5af46U + /* 112 */ , 0x7198540dU, 0x83f3d70eU, 0x90a324faU, 0x62c8a7f9U, 0xb602c312U, 0x44694011U, 0x5739b3e5U, 0xa55230e6U + /* 120 */ , 0xfb410cc2U, 0x092a8fc1U, 0x1a7a7c35U, 0xe811ff36U, 0x3cdb9bddU, 0xceb018deU, 0xdde0eb2aU, 0x2f8b6829U + /* 128 */ , 0x82f63b78U, 0x709db87bU, 0x63cd4b8fU, 0x91a6c88cU, 0x456cac67U, 0xb7072f64U, 0xa457dc90U, 0x563c5f93U + /* 136 */ , 0x082f63b7U, 0xfa44e0b4U, 0xe9141340U, 0x1b7f9043U, 0xcfb5f4a8U, 0x3dde77abU, 0x2e8e845fU, 0xdce5075cU + /* 144 */ , 0x92a8fc17U, 0x60c37f14U, 0x73938ce0U, 0x81f80fe3U, 0x55326b08U, 0xa759e80bU, 0xb4091bffU, 0x466298fcU + /* 152 */ , 0x1871a4d8U, 0xea1a27dbU, 0xf94ad42fU, 0x0b21572cU, 0xdfeb33c7U, 0x2d80b0c4U, 0x3ed04330U, 0xccbbc033U + /* 160 */ , 0xa24bb5a6U, 0x502036a5U, 0x4370c551U, 0xb11b4652U, 0x65d122b9U, 0x97baa1baU, 0x84ea524eU, 0x7681d14dU + /* 168 */ , 0x2892ed69U, 0xdaf96e6aU, 0xc9a99d9eU, 0x3bc21e9dU, 0xef087a76U, 0x1d63f975U, 0x0e330a81U, 0xfc588982U + /* 176 */ , 0xb21572c9U, 0x407ef1caU, 0x532e023eU, 0xa145813dU, 0x758fe5d6U, 0x87e466d5U, 0x94b49521U, 0x66df1622U + /* 184 */ , 0x38cc2a06U, 0xcaa7a905U, 0xd9f75af1U, 0x2b9cd9f2U, 0xff56bd19U, 0x0d3d3e1aU, 0x1e6dcdeeU, 0xec064eedU + /* 192 */ , 0xc38d26c4U, 0x31e6a5c7U, 0x22b65633U, 0xd0ddd530U, 0x0417b1dbU, 0xf67c32d8U, 0xe52cc12cU, 0x1747422fU + /* 200 */ , 0x49547e0bU, 0xbb3ffd08U, 0xa86f0efcU, 0x5a048dffU, 0x8ecee914U, 0x7ca56a17U, 0x6ff599e3U, 0x9d9e1ae0U + /* 208 */ , 0xd3d3e1abU, 0x21b862a8U, 0x32e8915cU, 0xc083125fU, 0x144976b4U, 0xe622f5b7U, 0xf5720643U, 0x07198540U + /* 216 */ , 0x590ab964U, 0xab613a67U, 0xb831c993U, 0x4a5a4a90U, 0x9e902e7bU, 0x6cfbad78U, 0x7fab5e8cU, 0x8dc0dd8fU + /* 224 */ , 0xe330a81aU, 0x115b2b19U, 0x020bd8edU, 0xf0605beeU, 0x24aa3f05U, 0xd6c1bc06U, 0xc5914ff2U, 0x37faccf1U + /* 232 */ , 0x69e9f0d5U, 0x9b8273d6U, 0x88d28022U, 0x7ab90321U, 0xae7367caU, 0x5c18e4c9U, 0x4f48173dU, 0xbd23943eU + /* 240 */ , 0xf36e6f75U, 0x0105ec76U, 0x12551f82U, 0xe03e9c81U, 0x34f4f86aU, 0xc69f7b69U, 0xd5cf889dU, 0x27a40b9eU + /* 248 */ , 0x79b737baU, 0x8bdcb4b9U, 0x988c474dU, 0x6ae7c44eU, 0xbe2da0a5U, 0x4c4623a6U, 0x5f16d052U, 0xad7d5351U + } + #ifdef CRC32_BYFOUR + , + /* CRC32C table 1 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x13a29877U, 0x274530eeU, 0x34e7a899U, 0x4e8a61dcU, 0x5d28f9abU, 0x69cf5132U, 0x7a6dc945U + /* 8 */ , 0x9d14c3b8U, 0x8eb65bcfU, 0xba51f356U, 0xa9f36b21U, 0xd39ea264U, 0xc03c3a13U, 0xf4db928aU, 0xe7790afdU + /* 16 */ , 0x3fc5f181U, 0x2c6769f6U, 0x1880c16fU, 0x0b225918U, 0x714f905dU, 0x62ed082aU, 0x560aa0b3U, 0x45a838c4U + /* 24 */ , 0xa2d13239U, 0xb173aa4eU, 0x859402d7U, 0x96369aa0U, 0xec5b53e5U, 0xfff9cb92U, 0xcb1e630bU, 0xd8bcfb7cU + /* 32 */ , 0x7f8be302U, 0x6c297b75U, 0x58ced3ecU, 0x4b6c4b9bU, 0x310182deU, 0x22a31aa9U, 0x1644b230U, 0x05e62a47U + /* 40 */ , 0xe29f20baU, 0xf13db8cdU, 0xc5da1054U, 0xd6788823U, 0xac154166U, 0xbfb7d911U, 0x8b507188U, 0x98f2e9ffU + /* 48 */ , 0x404e1283U, 0x53ec8af4U, 0x670b226dU, 0x74a9ba1aU, 0x0ec4735fU, 0x1d66eb28U, 0x298143b1U, 0x3a23dbc6U + /* 56 */ , 0xdd5ad13bU, 0xcef8494cU, 0xfa1fe1d5U, 0xe9bd79a2U, 0x93d0b0e7U, 0x80722890U, 0xb4958009U, 0xa737187eU + /* 64 */ , 0xff17c604U, 0xecb55e73U, 0xd852f6eaU, 0xcbf06e9dU, 0xb19da7d8U, 0xa23f3fafU, 0x96d89736U, 0x857a0f41U + /* 72 */ , 0x620305bcU, 0x71a19dcbU, 0x45463552U, 0x56e4ad25U, 0x2c896460U, 0x3f2bfc17U, 0x0bcc548eU, 0x186eccf9U + /* 80 */ , 0xc0d23785U, 0xd370aff2U, 0xe797076bU, 0xf4359f1cU, 0x8e585659U, 0x9dface2eU, 0xa91d66b7U, 0xbabffec0U + /* 88 */ , 0x5dc6f43dU, 0x4e646c4aU, 0x7a83c4d3U, 0x69215ca4U, 0x134c95e1U, 0x00ee0d96U, 0x3409a50fU, 0x27ab3d78U + /* 96 */ , 0x809c2506U, 0x933ebd71U, 0xa7d915e8U, 0xb47b8d9fU, 0xce1644daU, 0xddb4dcadU, 0xe9537434U, 0xfaf1ec43U + /* 104 */ , 0x1d88e6beU, 0x0e2a7ec9U, 0x3acdd650U, 0x296f4e27U, 0x53028762U, 0x40a01f15U, 0x7447b78cU, 0x67e52ffbU + /* 112 */ , 0xbf59d487U, 0xacfb4cf0U, 0x981ce469U, 0x8bbe7c1eU, 0xf1d3b55bU, 0xe2712d2cU, 0xd69685b5U, 0xc5341dc2U + /* 120 */ , 0x224d173fU, 0x31ef8f48U, 0x050827d1U, 0x16aabfa6U, 0x6cc776e3U, 0x7f65ee94U, 0x4b82460dU, 0x5820de7aU + /* 128 */ , 0xfbc3faf9U, 0xe861628eU, 0xdc86ca17U, 0xcf245260U, 0xb5499b25U, 0xa6eb0352U, 0x920cabcbU, 0x81ae33bcU + /* 136 */ , 0x66d73941U, 0x7575a136U, 0x419209afU, 0x523091d8U, 0x285d589dU, 0x3bffc0eaU, 0x0f186873U, 0x1cbaf004U + /* 144 */ , 0xc4060b78U, 0xd7a4930fU, 0xe3433b96U, 0xf0e1a3e1U, 0x8a8c6aa4U, 0x992ef2d3U, 0xadc95a4aU, 0xbe6bc23dU + /* 152 */ , 0x5912c8c0U, 0x4ab050b7U, 0x7e57f82eU, 0x6df56059U, 0x1798a91cU, 0x043a316bU, 0x30dd99f2U, 0x237f0185U + /* 160 */ , 0x844819fbU, 0x97ea818cU, 0xa30d2915U, 0xb0afb162U, 0xcac27827U, 0xd960e050U, 0xed8748c9U, 0xfe25d0beU + /* 168 */ , 0x195cda43U, 0x0afe4234U, 0x3e19eaadU, 0x2dbb72daU, 0x57d6bb9fU, 0x447423e8U, 0x70938b71U, 0x63311306U + /* 176 */ , 0xbb8de87aU, 0xa82f700dU, 0x9cc8d894U, 0x8f6a40e3U, 0xf50789a6U, 0xe6a511d1U, 0xd242b948U, 0xc1e0213fU + /* 184 */ , 0x26992bc2U, 0x353bb3b5U, 0x01dc1b2cU, 0x127e835bU, 0x68134a1eU, 0x7bb1d269U, 0x4f567af0U, 0x5cf4e287U + /* 192 */ , 0x04d43cfdU, 0x1776a48aU, 0x23910c13U, 0x30339464U, 0x4a5e5d21U, 0x59fcc556U, 0x6d1b6dcfU, 0x7eb9f5b8U + /* 200 */ , 0x99c0ff45U, 0x8a626732U, 0xbe85cfabU, 0xad2757dcU, 0xd74a9e99U, 0xc4e806eeU, 0xf00fae77U, 0xe3ad3600U + /* 208 */ , 0x3b11cd7cU, 0x28b3550bU, 0x1c54fd92U, 0x0ff665e5U, 0x759baca0U, 0x663934d7U, 0x52de9c4eU, 0x417c0439U + /* 216 */ , 0xa6050ec4U, 0xb5a796b3U, 0x81403e2aU, 0x92e2a65dU, 0xe88f6f18U, 0xfb2df76fU, 0xcfca5ff6U, 0xdc68c781U + /* 224 */ , 0x7b5fdfffU, 0x68fd4788U, 0x5c1aef11U, 0x4fb87766U, 0x35d5be23U, 0x26772654U, 0x12908ecdU, 0x013216baU + /* 232 */ , 0xe64b1c47U, 0xf5e98430U, 0xc10e2ca9U, 0xd2acb4deU, 0xa8c17d9bU, 0xbb63e5ecU, 0x8f844d75U, 0x9c26d502U + /* 240 */ , 0x449a2e7eU, 0x5738b609U, 0x63df1e90U, 0x707d86e7U, 0x0a104fa2U, 0x19b2d7d5U, 0x2d557f4cU, 0x3ef7e73bU + /* 248 */ , 0xd98eedc6U, 0xca2c75b1U, 0xfecbdd28U, 0xed69455fU, 0x97048c1aU, 0x84a6146dU, 0xb041bcf4U, 0xa3e32483U + } + , + /* CRC32C table 2 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xa541927eU, 0x4f6f520dU, 0xea2ec073U, 0x9edea41aU, 0x3b9f3664U, 0xd1b1f617U, 0x74f06469U + /* 8 */ , 0x38513ec5U, 0x9d10acbbU, 0x773e6cc8U, 0xd27ffeb6U, 0xa68f9adfU, 0x03ce08a1U, 0xe9e0c8d2U, 0x4ca15aacU + /* 16 */ , 0x70a27d8aU, 0xd5e3eff4U, 0x3fcd2f87U, 0x9a8cbdf9U, 0xee7cd990U, 0x4b3d4beeU, 0xa1138b9dU, 0x045219e3U + /* 24 */ , 0x48f3434fU, 0xedb2d131U, 0x079c1142U, 0xa2dd833cU, 0xd62de755U, 0x736c752bU, 0x9942b558U, 0x3c032726U + /* 32 */ , 0xe144fb14U, 0x4405696aU, 0xae2ba919U, 0x0b6a3b67U, 0x7f9a5f0eU, 0xdadbcd70U, 0x30f50d03U, 0x95b49f7dU + /* 40 */ , 0xd915c5d1U, 0x7c5457afU, 0x967a97dcU, 0x333b05a2U, 0x47cb61cbU, 0xe28af3b5U, 0x08a433c6U, 0xade5a1b8U + /* 48 */ , 0x91e6869eU, 0x34a714e0U, 0xde89d493U, 0x7bc846edU, 0x0f382284U, 0xaa79b0faU, 0x40577089U, 0xe516e2f7U + /* 56 */ , 0xa9b7b85bU, 0x0cf62a25U, 0xe6d8ea56U, 0x43997828U, 0x37691c41U, 0x92288e3fU, 0x78064e4cU, 0xdd47dc32U + /* 64 */ , 0xc76580d9U, 0x622412a7U, 0x880ad2d4U, 0x2d4b40aaU, 0x59bb24c3U, 0xfcfab6bdU, 0x16d476ceU, 0xb395e4b0U + /* 72 */ , 0xff34be1cU, 0x5a752c62U, 0xb05bec11U, 0x151a7e6fU, 0x61ea1a06U, 0xc4ab8878U, 0x2e85480bU, 0x8bc4da75U + /* 80 */ , 0xb7c7fd53U, 0x12866f2dU, 0xf8a8af5eU, 0x5de93d20U, 0x29195949U, 0x8c58cb37U, 0x66760b44U, 0xc337993aU + /* 88 */ , 0x8f96c396U, 0x2ad751e8U, 0xc0f9919bU, 0x65b803e5U, 0x1148678cU, 0xb409f5f2U, 0x5e273581U, 0xfb66a7ffU + /* 96 */ , 0x26217bcdU, 0x8360e9b3U, 0x694e29c0U, 0xcc0fbbbeU, 0xb8ffdfd7U, 0x1dbe4da9U, 0xf7908ddaU, 0x52d11fa4U + /* 104 */ , 0x1e704508U, 0xbb31d776U, 0x511f1705U, 0xf45e857bU, 0x80aee112U, 0x25ef736cU, 0xcfc1b31fU, 0x6a802161U + /* 112 */ , 0x56830647U, 0xf3c29439U, 0x19ec544aU, 0xbcadc634U, 0xc85da25dU, 0x6d1c3023U, 0x8732f050U, 0x2273622eU + /* 120 */ , 0x6ed23882U, 0xcb93aafcU, 0x21bd6a8fU, 0x84fcf8f1U, 0xf00c9c98U, 0x554d0ee6U, 0xbf63ce95U, 0x1a225cebU + /* 128 */ , 0x8b277743U, 0x2e66e53dU, 0xc448254eU, 0x6109b730U, 0x15f9d359U, 0xb0b84127U, 0x5a968154U, 0xffd7132aU + /* 136 */ , 0xb3764986U, 0x1637dbf8U, 0xfc191b8bU, 0x595889f5U, 0x2da8ed9cU, 0x88e97fe2U, 0x62c7bf91U, 0xc7862defU + /* 144 */ , 0xfb850ac9U, 0x5ec498b7U, 0xb4ea58c4U, 0x11abcabaU, 0x655baed3U, 0xc01a3cadU, 0x2a34fcdeU, 0x8f756ea0U + /* 152 */ , 0xc3d4340cU, 0x6695a672U, 0x8cbb6601U, 0x29faf47fU, 0x5d0a9016U, 0xf84b0268U, 0x1265c21bU, 0xb7245065U + /* 160 */ , 0x6a638c57U, 0xcf221e29U, 0x250cde5aU, 0x804d4c24U, 0xf4bd284dU, 0x51fcba33U, 0xbbd27a40U, 0x1e93e83eU + /* 168 */ , 0x5232b292U, 0xf77320ecU, 0x1d5de09fU, 0xb81c72e1U, 0xccec1688U, 0x69ad84f6U, 0x83834485U, 0x26c2d6fbU + /* 176 */ , 0x1ac1f1ddU, 0xbf8063a3U, 0x55aea3d0U, 0xf0ef31aeU, 0x841f55c7U, 0x215ec7b9U, 0xcb7007caU, 0x6e3195b4U + /* 184 */ , 0x2290cf18U, 0x87d15d66U, 0x6dff9d15U, 0xc8be0f6bU, 0xbc4e6b02U, 0x190ff97cU, 0xf321390fU, 0x5660ab71U + /* 192 */ , 0x4c42f79aU, 0xe90365e4U, 0x032da597U, 0xa66c37e9U, 0xd29c5380U, 0x77ddc1feU, 0x9df3018dU, 0x38b293f3U + /* 200 */ , 0x7413c95fU, 0xd1525b21U, 0x3b7c9b52U, 0x9e3d092cU, 0xeacd6d45U, 0x4f8cff3bU, 0xa5a23f48U, 0x00e3ad36U + /* 208 */ , 0x3ce08a10U, 0x99a1186eU, 0x738fd81dU, 0xd6ce4a63U, 0xa23e2e0aU, 0x077fbc74U, 0xed517c07U, 0x4810ee79U + /* 216 */ , 0x04b1b4d5U, 0xa1f026abU, 0x4bdee6d8U, 0xee9f74a6U, 0x9a6f10cfU, 0x3f2e82b1U, 0xd50042c2U, 0x7041d0bcU + /* 224 */ , 0xad060c8eU, 0x08479ef0U, 0xe2695e83U, 0x4728ccfdU, 0x33d8a894U, 0x96993aeaU, 0x7cb7fa99U, 0xd9f668e7U + /* 232 */ , 0x9557324bU, 0x3016a035U, 0xda386046U, 0x7f79f238U, 0x0b899651U, 0xaec8042fU, 0x44e6c45cU, 0xe1a75622U + /* 240 */ , 0xdda47104U, 0x78e5e37aU, 0x92cb2309U, 0x378ab177U, 0x437ad51eU, 0xe63b4760U, 0x0c158713U, 0xa954156dU + /* 248 */ , 0xe5f54fc1U, 0x40b4ddbfU, 0xaa9a1dccU, 0x0fdb8fb2U, 0x7b2bebdbU, 0xde6a79a5U, 0x3444b9d6U, 0x91052ba8U + } + , + /* CRC32C table 3 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xdd45aab8U, 0xbf672381U, 0x62228939U, 0x7b2231f3U, 0xa6679b4bU, 0xc4451272U, 0x1900b8caU + /* 8 */ , 0xf64463e6U, 0x2b01c95eU, 0x49234067U, 0x9466eadfU, 0x8d665215U, 0x5023f8adU, 0x32017194U, 0xef44db2cU + /* 16 */ , 0xe964b13dU, 0x34211b85U, 0x560392bcU, 0x8b463804U, 0x924680ceU, 0x4f032a76U, 0x2d21a34fU, 0xf06409f7U + /* 24 */ , 0x1f20d2dbU, 0xc2657863U, 0xa047f15aU, 0x7d025be2U, 0x6402e328U, 0xb9474990U, 0xdb65c0a9U, 0x06206a11U + /* 32 */ , 0xd725148bU, 0x0a60be33U, 0x6842370aU, 0xb5079db2U, 0xac072578U, 0x71428fc0U, 0x136006f9U, 0xce25ac41U + /* 40 */ , 0x2161776dU, 0xfc24ddd5U, 0x9e0654ecU, 0x4343fe54U, 0x5a43469eU, 0x8706ec26U, 0xe524651fU, 0x3861cfa7U + /* 48 */ , 0x3e41a5b6U, 0xe3040f0eU, 0x81268637U, 0x5c632c8fU, 0x45639445U, 0x98263efdU, 0xfa04b7c4U, 0x27411d7cU + /* 56 */ , 0xc805c650U, 0x15406ce8U, 0x7762e5d1U, 0xaa274f69U, 0xb327f7a3U, 0x6e625d1bU, 0x0c40d422U, 0xd1057e9aU + /* 64 */ , 0xaba65fe7U, 0x76e3f55fU, 0x14c17c66U, 0xc984d6deU, 0xd0846e14U, 0x0dc1c4acU, 0x6fe34d95U, 0xb2a6e72dU + /* 72 */ , 0x5de23c01U, 0x80a796b9U, 0xe2851f80U, 0x3fc0b538U, 0x26c00df2U, 0xfb85a74aU, 0x99a72e73U, 0x44e284cbU + /* 80 */ , 0x42c2eedaU, 0x9f874462U, 0xfda5cd5bU, 0x20e067e3U, 0x39e0df29U, 0xe4a57591U, 0x8687fca8U, 0x5bc25610U + /* 88 */ , 0xb4868d3cU, 0x69c32784U, 0x0be1aebdU, 0xd6a40405U, 0xcfa4bccfU, 0x12e11677U, 0x70c39f4eU, 0xad8635f6U + /* 96 */ , 0x7c834b6cU, 0xa1c6e1d4U, 0xc3e468edU, 0x1ea1c255U, 0x07a17a9fU, 0xdae4d027U, 0xb8c6591eU, 0x6583f3a6U + /* 104 */ , 0x8ac7288aU, 0x57828232U, 0x35a00b0bU, 0xe8e5a1b3U, 0xf1e51979U, 0x2ca0b3c1U, 0x4e823af8U, 0x93c79040U + /* 112 */ , 0x95e7fa51U, 0x48a250e9U, 0x2a80d9d0U, 0xf7c57368U, 0xeec5cba2U, 0x3380611aU, 0x51a2e823U, 0x8ce7429bU + /* 120 */ , 0x63a399b7U, 0xbee6330fU, 0xdcc4ba36U, 0x0181108eU, 0x1881a844U, 0xc5c402fcU, 0xa7e68bc5U, 0x7aa3217dU + /* 128 */ , 0x52a0c93fU, 0x8fe56387U, 0xedc7eabeU, 0x30824006U, 0x2982f8ccU, 0xf4c75274U, 0x96e5db4dU, 0x4ba071f5U + /* 136 */ , 0xa4e4aad9U, 0x79a10061U, 0x1b838958U, 0xc6c623e0U, 0xdfc69b2aU, 0x02833192U, 0x60a1b8abU, 0xbde41213U + /* 144 */ , 0xbbc47802U, 0x6681d2baU, 0x04a35b83U, 0xd9e6f13bU, 0xc0e649f1U, 0x1da3e349U, 0x7f816a70U, 0xa2c4c0c8U + /* 152 */ , 0x4d801be4U, 0x90c5b15cU, 0xf2e73865U, 0x2fa292ddU, 0x36a22a17U, 0xebe780afU, 0x89c50996U, 0x5480a32eU + /* 160 */ , 0x8585ddb4U, 0x58c0770cU, 0x3ae2fe35U, 0xe7a7548dU, 0xfea7ec47U, 0x23e246ffU, 0x41c0cfc6U, 0x9c85657eU + /* 168 */ , 0x73c1be52U, 0xae8414eaU, 0xcca69dd3U, 0x11e3376bU, 0x08e38fa1U, 0xd5a62519U, 0xb784ac20U, 0x6ac10698U + /* 176 */ , 0x6ce16c89U, 0xb1a4c631U, 0xd3864f08U, 0x0ec3e5b0U, 0x17c35d7aU, 0xca86f7c2U, 0xa8a47efbU, 0x75e1d443U + /* 184 */ , 0x9aa50f6fU, 0x47e0a5d7U, 0x25c22ceeU, 0xf8878656U, 0xe1873e9cU, 0x3cc29424U, 0x5ee01d1dU, 0x83a5b7a5U + /* 192 */ , 0xf90696d8U, 0x24433c60U, 0x4661b559U, 0x9b241fe1U, 0x8224a72bU, 0x5f610d93U, 0x3d4384aaU, 0xe0062e12U + /* 200 */ , 0x0f42f53eU, 0xd2075f86U, 0xb025d6bfU, 0x6d607c07U, 0x7460c4cdU, 0xa9256e75U, 0xcb07e74cU, 0x16424df4U + /* 208 */ , 0x106227e5U, 0xcd278d5dU, 0xaf050464U, 0x7240aedcU, 0x6b401616U, 0xb605bcaeU, 0xd4273597U, 0x09629f2fU + /* 216 */ , 0xe6264403U, 0x3b63eebbU, 0x59416782U, 0x8404cd3aU, 0x9d0475f0U, 0x4041df48U, 0x22635671U, 0xff26fcc9U + /* 224 */ , 0x2e238253U, 0xf36628ebU, 0x9144a1d2U, 0x4c010b6aU, 0x5501b3a0U, 0x88441918U, 0xea669021U, 0x37233a99U + /* 232 */ , 0xd867e1b5U, 0x05224b0dU, 0x6700c234U, 0xba45688cU, 0xa345d046U, 0x7e007afeU, 0x1c22f3c7U, 0xc167597fU + /* 240 */ , 0xc747336eU, 0x1a0299d6U, 0x782010efU, 0xa565ba57U, 0xbc65029dU, 0x6120a825U, 0x0302211cU, 0xde478ba4U + /* 248 */ , 0x31035088U, 0xec46fa30U, 0x8e647309U, 0x5321d9b1U, 0x4a21617bU, 0x9764cbc3U, 0xf54642faU, 0x2803e842U + } + , + /* CRC32C table 4 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x03836bf2U, 0xf7703be1U, 0xf4f35013U, 0x1f979ac7U, 0x1c14f135U, 0xe8e7a126U, 0xeb64cad4U + /* 8 */ , 0xcf58d98aU, 0xccdbb278U, 0x3828e26bU, 0x3bab8999U, 0xd0cf434dU, 0xd34c28bfU, 0x27bf78acU, 0x243c135eU + /* 16 */ , 0x6fc75e10U, 0x6c4435e2U, 0x98b765f1U, 0x9b340e03U, 0x7050c4d7U, 0x73d3af25U, 0x8720ff36U, 0x84a394c4U + /* 24 */ , 0xa09f879aU, 0xa31cec68U, 0x57efbc7bU, 0x546cd789U, 0xbf081d5dU, 0xbc8b76afU, 0x487826bcU, 0x4bfb4d4eU + /* 32 */ , 0xde8ebd20U, 0xdd0dd6d2U, 0x29fe86c1U, 0x2a7ded33U, 0xc11927e7U, 0xc29a4c15U, 0x36691c06U, 0x35ea77f4U + /* 40 */ , 0x11d664aaU, 0x12550f58U, 0xe6a65f4bU, 0xe52534b9U, 0x0e41fe6dU, 0x0dc2959fU, 0xf931c58cU, 0xfab2ae7eU + /* 48 */ , 0xb149e330U, 0xb2ca88c2U, 0x4639d8d1U, 0x45bab323U, 0xaede79f7U, 0xad5d1205U, 0x59ae4216U, 0x5a2d29e4U + /* 56 */ , 0x7e113abaU, 0x7d925148U, 0x8961015bU, 0x8ae26aa9U, 0x6186a07dU, 0x6205cb8fU, 0x96f69b9cU, 0x9575f06eU + /* 64 */ , 0xbc1d7b41U, 0xbf9e10b3U, 0x4b6d40a0U, 0x48ee2b52U, 0xa38ae186U, 0xa0098a74U, 0x54fada67U, 0x5779b195U + /* 72 */ , 0x7345a2cbU, 0x70c6c939U, 0x8435992aU, 0x87b6f2d8U, 0x6cd2380cU, 0x6f5153feU, 0x9ba203edU, 0x9821681fU + /* 80 */ , 0xd3da2551U, 0xd0594ea3U, 0x24aa1eb0U, 0x27297542U, 0xcc4dbf96U, 0xcfced464U, 0x3b3d8477U, 0x38beef85U + /* 88 */ , 0x1c82fcdbU, 0x1f019729U, 0xebf2c73aU, 0xe871acc8U, 0x0315661cU, 0x00960deeU, 0xf4655dfdU, 0xf7e6360fU + /* 96 */ , 0x6293c661U, 0x6110ad93U, 0x95e3fd80U, 0x96609672U, 0x7d045ca6U, 0x7e873754U, 0x8a746747U, 0x89f70cb5U + /* 104 */ , 0xadcb1febU, 0xae487419U, 0x5abb240aU, 0x59384ff8U, 0xb25c852cU, 0xb1dfeedeU, 0x452cbecdU, 0x46afd53fU + /* 112 */ , 0x0d549871U, 0x0ed7f383U, 0xfa24a390U, 0xf9a7c862U, 0x12c302b6U, 0x11406944U, 0xe5b33957U, 0xe63052a5U + /* 120 */ , 0xc20c41fbU, 0xc18f2a09U, 0x357c7a1aU, 0x36ff11e8U, 0xdd9bdb3cU, 0xde18b0ceU, 0x2aebe0ddU, 0x29688b2fU + /* 128 */ , 0x783bf682U, 0x7bb89d70U, 0x8f4bcd63U, 0x8cc8a691U, 0x67ac6c45U, 0x642f07b7U, 0x90dc57a4U, 0x935f3c56U + /* 136 */ , 0xb7632f08U, 0xb4e044faU, 0x401314e9U, 0x43907f1bU, 0xa8f4b5cfU, 0xab77de3dU, 0x5f848e2eU, 0x5c07e5dcU + /* 144 */ , 0x17fca892U, 0x147fc360U, 0xe08c9373U, 0xe30ff881U, 0x086b3255U, 0x0be859a7U, 0xff1b09b4U, 0xfc986246U + /* 152 */ , 0xd8a47118U, 0xdb271aeaU, 0x2fd44af9U, 0x2c57210bU, 0xc733ebdfU, 0xc4b0802dU, 0x3043d03eU, 0x33c0bbccU + /* 160 */ , 0xa6b54ba2U, 0xa5362050U, 0x51c57043U, 0x52461bb1U, 0xb922d165U, 0xbaa1ba97U, 0x4e52ea84U, 0x4dd18176U + /* 168 */ , 0x69ed9228U, 0x6a6ef9daU, 0x9e9da9c9U, 0x9d1ec23bU, 0x767a08efU, 0x75f9631dU, 0x810a330eU, 0x828958fcU + /* 176 */ , 0xc97215b2U, 0xcaf17e40U, 0x3e022e53U, 0x3d8145a1U, 0xd6e58f75U, 0xd566e487U, 0x2195b494U, 0x2216df66U + /* 184 */ , 0x062acc38U, 0x05a9a7caU, 0xf15af7d9U, 0xf2d99c2bU, 0x19bd56ffU, 0x1a3e3d0dU, 0xeecd6d1eU, 0xed4e06ecU + /* 192 */ , 0xc4268dc3U, 0xc7a5e631U, 0x3356b622U, 0x30d5ddd0U, 0xdbb11704U, 0xd8327cf6U, 0x2cc12ce5U, 0x2f424717U + /* 200 */ , 0x0b7e5449U, 0x08fd3fbbU, 0xfc0e6fa8U, 0xff8d045aU, 0x14e9ce8eU, 0x176aa57cU, 0xe399f56fU, 0xe01a9e9dU + /* 208 */ , 0xabe1d3d3U, 0xa862b821U, 0x5c91e832U, 0x5f1283c0U, 0xb4764914U, 0xb7f522e6U, 0x430672f5U, 0x40851907U + /* 216 */ , 0x64b90a59U, 0x673a61abU, 0x93c931b8U, 0x904a5a4aU, 0x7b2e909eU, 0x78adfb6cU, 0x8c5eab7fU, 0x8fddc08dU + /* 224 */ , 0x1aa830e3U, 0x192b5b11U, 0xedd80b02U, 0xee5b60f0U, 0x053faa24U, 0x06bcc1d6U, 0xf24f91c5U, 0xf1ccfa37U + /* 232 */ , 0xd5f0e969U, 0xd673829bU, 0x2280d288U, 0x2103b97aU, 0xca6773aeU, 0xc9e4185cU, 0x3d17484fU, 0x3e9423bdU + /* 240 */ , 0x756f6ef3U, 0x76ec0501U, 0x821f5512U, 0x819c3ee0U, 0x6af8f434U, 0x697b9fc6U, 0x9d88cfd5U, 0x9e0ba427U + /* 248 */ , 0xba37b779U, 0xb9b4dc8bU, 0x4d478c98U, 0x4ec4e76aU, 0xa5a02dbeU, 0xa623464cU, 0x52d0165fU, 0x51537dadU + } + , + /* CRC32C table 5 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x7798a213U, 0xee304527U, 0x99a8e734U, 0xdc618a4eU, 0xabf9285dU, 0x3251cf69U, 0x45c96d7aU + /* 8 */ , 0xb8c3149dU, 0xcf5bb68eU, 0x56f351baU, 0x216bf3a9U, 0x64a29ed3U, 0x133a3cc0U, 0x8a92dbf4U, 0xfd0a79e7U + /* 16 */ , 0x81f1c53fU, 0xf669672cU, 0x6fc18018U, 0x1859220bU, 0x5d904f71U, 0x2a08ed62U, 0xb3a00a56U, 0xc438a845U + /* 24 */ , 0x3932d1a2U, 0x4eaa73b1U, 0xd7029485U, 0xa09a3696U, 0xe5535becU, 0x92cbf9ffU, 0x0b631ecbU, 0x7cfbbcd8U + /* 32 */ , 0x02e38b7fU, 0x757b296cU, 0xecd3ce58U, 0x9b4b6c4bU, 0xde820131U, 0xa91aa322U, 0x30b24416U, 0x472ae605U + /* 40 */ , 0xba209fe2U, 0xcdb83df1U, 0x5410dac5U, 0x238878d6U, 0x664115acU, 0x11d9b7bfU, 0x8871508bU, 0xffe9f298U + /* 48 */ , 0x83124e40U, 0xf48aec53U, 0x6d220b67U, 0x1abaa974U, 0x5f73c40eU, 0x28eb661dU, 0xb1438129U, 0xc6db233aU + /* 56 */ , 0x3bd15addU, 0x4c49f8ceU, 0xd5e11ffaU, 0xa279bde9U, 0xe7b0d093U, 0x90287280U, 0x098095b4U, 0x7e1837a7U + /* 64 */ , 0x04c617ffU, 0x735eb5ecU, 0xeaf652d8U, 0x9d6ef0cbU, 0xd8a79db1U, 0xaf3f3fa2U, 0x3697d896U, 0x410f7a85U + /* 72 */ , 0xbc050362U, 0xcb9da171U, 0x52354645U, 0x25ade456U, 0x6064892cU, 0x17fc2b3fU, 0x8e54cc0bU, 0xf9cc6e18U + /* 80 */ , 0x8537d2c0U, 0xf2af70d3U, 0x6b0797e7U, 0x1c9f35f4U, 0x5956588eU, 0x2ecefa9dU, 0xb7661da9U, 0xc0febfbaU + /* 88 */ , 0x3df4c65dU, 0x4a6c644eU, 0xd3c4837aU, 0xa45c2169U, 0xe1954c13U, 0x960dee00U, 0x0fa50934U, 0x783dab27U + /* 96 */ , 0x06259c80U, 0x71bd3e93U, 0xe815d9a7U, 0x9f8d7bb4U, 0xda4416ceU, 0xaddcb4ddU, 0x347453e9U, 0x43ecf1faU + /* 104 */ , 0xbee6881dU, 0xc97e2a0eU, 0x50d6cd3aU, 0x274e6f29U, 0x62870253U, 0x151fa040U, 0x8cb74774U, 0xfb2fe567U + /* 112 */ , 0x87d459bfU, 0xf04cfbacU, 0x69e41c98U, 0x1e7cbe8bU, 0x5bb5d3f1U, 0x2c2d71e2U, 0xb58596d6U, 0xc21d34c5U + /* 120 */ , 0x3f174d22U, 0x488fef31U, 0xd1270805U, 0xa6bfaa16U, 0xe376c76cU, 0x94ee657fU, 0x0d46824bU, 0x7ade2058U + /* 128 */ , 0xf9fac3fbU, 0x8e6261e8U, 0x17ca86dcU, 0x605224cfU, 0x259b49b5U, 0x5203eba6U, 0xcbab0c92U, 0xbc33ae81U + /* 136 */ , 0x4139d766U, 0x36a17575U, 0xaf099241U, 0xd8913052U, 0x9d585d28U, 0xeac0ff3bU, 0x7368180fU, 0x04f0ba1cU + /* 144 */ , 0x780b06c4U, 0x0f93a4d7U, 0x963b43e3U, 0xe1a3e1f0U, 0xa46a8c8aU, 0xd3f22e99U, 0x4a5ac9adU, 0x3dc26bbeU + /* 152 */ , 0xc0c81259U, 0xb750b04aU, 0x2ef8577eU, 0x5960f56dU, 0x1ca99817U, 0x6b313a04U, 0xf299dd30U, 0x85017f23U + /* 160 */ , 0xfb194884U, 0x8c81ea97U, 0x15290da3U, 0x62b1afb0U, 0x2778c2caU, 0x50e060d9U, 0xc94887edU, 0xbed025feU + /* 168 */ , 0x43da5c19U, 0x3442fe0aU, 0xadea193eU, 0xda72bb2dU, 0x9fbbd657U, 0xe8237444U, 0x718b9370U, 0x06133163U + /* 176 */ , 0x7ae88dbbU, 0x0d702fa8U, 0x94d8c89cU, 0xe3406a8fU, 0xa68907f5U, 0xd111a5e6U, 0x48b942d2U, 0x3f21e0c1U + /* 184 */ , 0xc22b9926U, 0xb5b33b35U, 0x2c1bdc01U, 0x5b837e12U, 0x1e4a1368U, 0x69d2b17bU, 0xf07a564fU, 0x87e2f45cU + /* 192 */ , 0xfd3cd404U, 0x8aa47617U, 0x130c9123U, 0x64943330U, 0x215d5e4aU, 0x56c5fc59U, 0xcf6d1b6dU, 0xb8f5b97eU + /* 200 */ , 0x45ffc099U, 0x3267628aU, 0xabcf85beU, 0xdc5727adU, 0x999e4ad7U, 0xee06e8c4U, 0x77ae0ff0U, 0x0036ade3U + /* 208 */ , 0x7ccd113bU, 0x0b55b328U, 0x92fd541cU, 0xe565f60fU, 0xa0ac9b75U, 0xd7343966U, 0x4e9cde52U, 0x39047c41U + /* 216 */ , 0xc40e05a6U, 0xb396a7b5U, 0x2a3e4081U, 0x5da6e292U, 0x186f8fe8U, 0x6ff72dfbU, 0xf65fcacfU, 0x81c768dcU + /* 224 */ , 0xffdf5f7bU, 0x8847fd68U, 0x11ef1a5cU, 0x6677b84fU, 0x23bed535U, 0x54267726U, 0xcd8e9012U, 0xba163201U + /* 232 */ , 0x471c4be6U, 0x3084e9f5U, 0xa92c0ec1U, 0xdeb4acd2U, 0x9b7dc1a8U, 0xece563bbU, 0x754d848fU, 0x02d5269cU + /* 240 */ , 0x7e2e9a44U, 0x09b63857U, 0x901edf63U, 0xe7867d70U, 0xa24f100aU, 0xd5d7b219U, 0x4c7f552dU, 0x3be7f73eU + /* 248 */ , 0xc6ed8ed9U, 0xb1752ccaU, 0x28ddcbfeU, 0x5f4569edU, 0x1a8c0497U, 0x6d14a684U, 0xf4bc41b0U, 0x8324e3a3U + } + , + /* CRC32C table 6 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x7e9241a5U, 0x0d526f4fU, 0x73c02eeaU, 0x1aa4de9eU, 0x64369f3bU, 0x17f6b1d1U, 0x6964f074U + /* 8 */ , 0xc53e5138U, 0xbbac109dU, 0xc86c3e77U, 0xb6fe7fd2U, 0xdf9a8fa6U, 0xa108ce03U, 0xd2c8e0e9U, 0xac5aa14cU + /* 16 */ , 0x8a7da270U, 0xf4efe3d5U, 0x872fcd3fU, 0xf9bd8c9aU, 0x90d97ceeU, 0xee4b3d4bU, 0x9d8b13a1U, 0xe3195204U + /* 24 */ , 0x4f43f348U, 0x31d1b2edU, 0x42119c07U, 0x3c83dda2U, 0x55e72dd6U, 0x2b756c73U, 0x58b54299U, 0x2627033cU + /* 32 */ , 0x14fb44e1U, 0x6a690544U, 0x19a92baeU, 0x673b6a0bU, 0x0e5f9a7fU, 0x70cddbdaU, 0x030df530U, 0x7d9fb495U + /* 40 */ , 0xd1c515d9U, 0xaf57547cU, 0xdc977a96U, 0xa2053b33U, 0xcb61cb47U, 0xb5f38ae2U, 0xc633a408U, 0xb8a1e5adU + /* 48 */ , 0x9e86e691U, 0xe014a734U, 0x93d489deU, 0xed46c87bU, 0x8422380fU, 0xfab079aaU, 0x89705740U, 0xf7e216e5U + /* 56 */ , 0x5bb8b7a9U, 0x252af60cU, 0x56ead8e6U, 0x28789943U, 0x411c6937U, 0x3f8e2892U, 0x4c4e0678U, 0x32dc47ddU + /* 64 */ , 0xd98065c7U, 0xa7122462U, 0xd4d20a88U, 0xaa404b2dU, 0xc324bb59U, 0xbdb6fafcU, 0xce76d416U, 0xb0e495b3U + /* 72 */ , 0x1cbe34ffU, 0x622c755aU, 0x11ec5bb0U, 0x6f7e1a15U, 0x061aea61U, 0x7888abc4U, 0x0b48852eU, 0x75dac48bU + /* 80 */ , 0x53fdc7b7U, 0x2d6f8612U, 0x5eafa8f8U, 0x203de95dU, 0x49591929U, 0x37cb588cU, 0x440b7666U, 0x3a9937c3U + /* 88 */ , 0x96c3968fU, 0xe851d72aU, 0x9b91f9c0U, 0xe503b865U, 0x8c674811U, 0xf2f509b4U, 0x8135275eU, 0xffa766fbU + /* 96 */ , 0xcd7b2126U, 0xb3e96083U, 0xc0294e69U, 0xbebb0fccU, 0xd7dfffb8U, 0xa94dbe1dU, 0xda8d90f7U, 0xa41fd152U + /* 104 */ , 0x0845701eU, 0x76d731bbU, 0x05171f51U, 0x7b855ef4U, 0x12e1ae80U, 0x6c73ef25U, 0x1fb3c1cfU, 0x6121806aU + /* 112 */ , 0x47068356U, 0x3994c2f3U, 0x4a54ec19U, 0x34c6adbcU, 0x5da25dc8U, 0x23301c6dU, 0x50f03287U, 0x2e627322U + /* 120 */ , 0x8238d26eU, 0xfcaa93cbU, 0x8f6abd21U, 0xf1f8fc84U, 0x989c0cf0U, 0xe60e4d55U, 0x95ce63bfU, 0xeb5c221aU + /* 128 */ , 0x4377278bU, 0x3de5662eU, 0x4e2548c4U, 0x30b70961U, 0x59d3f915U, 0x2741b8b0U, 0x5481965aU, 0x2a13d7ffU + /* 136 */ , 0x864976b3U, 0xf8db3716U, 0x8b1b19fcU, 0xf5895859U, 0x9ceda82dU, 0xe27fe988U, 0x91bfc762U, 0xef2d86c7U + /* 144 */ , 0xc90a85fbU, 0xb798c45eU, 0xc458eab4U, 0xbacaab11U, 0xd3ae5b65U, 0xad3c1ac0U, 0xdefc342aU, 0xa06e758fU + /* 152 */ , 0x0c34d4c3U, 0x72a69566U, 0x0166bb8cU, 0x7ff4fa29U, 0x16900a5dU, 0x68024bf8U, 0x1bc26512U, 0x655024b7U + /* 160 */ , 0x578c636aU, 0x291e22cfU, 0x5ade0c25U, 0x244c4d80U, 0x4d28bdf4U, 0x33bafc51U, 0x407ad2bbU, 0x3ee8931eU + /* 168 */ , 0x92b23252U, 0xec2073f7U, 0x9fe05d1dU, 0xe1721cb8U, 0x8816ecccU, 0xf684ad69U, 0x85448383U, 0xfbd6c226U + /* 176 */ , 0xddf1c11aU, 0xa36380bfU, 0xd0a3ae55U, 0xae31eff0U, 0xc7551f84U, 0xb9c75e21U, 0xca0770cbU, 0xb495316eU + /* 184 */ , 0x18cf9022U, 0x665dd187U, 0x159dff6dU, 0x6b0fbec8U, 0x026b4ebcU, 0x7cf90f19U, 0x0f3921f3U, 0x71ab6056U + /* 192 */ , 0x9af7424cU, 0xe46503e9U, 0x97a52d03U, 0xe9376ca6U, 0x80539cd2U, 0xfec1dd77U, 0x8d01f39dU, 0xf393b238U + /* 200 */ , 0x5fc91374U, 0x215b52d1U, 0x529b7c3bU, 0x2c093d9eU, 0x456dcdeaU, 0x3bff8c4fU, 0x483fa2a5U, 0x36ade300U + /* 208 */ , 0x108ae03cU, 0x6e18a199U, 0x1dd88f73U, 0x634aced6U, 0x0a2e3ea2U, 0x74bc7f07U, 0x077c51edU, 0x79ee1048U + /* 216 */ , 0xd5b4b104U, 0xab26f0a1U, 0xd8e6de4bU, 0xa6749feeU, 0xcf106f9aU, 0xb1822e3fU, 0xc24200d5U, 0xbcd04170U + /* 224 */ , 0x8e0c06adU, 0xf09e4708U, 0x835e69e2U, 0xfdcc2847U, 0x94a8d833U, 0xea3a9996U, 0x99fab77cU, 0xe768f6d9U + /* 232 */ , 0x4b325795U, 0x35a01630U, 0x466038daU, 0x38f2797fU, 0x5196890bU, 0x2f04c8aeU, 0x5cc4e644U, 0x2256a7e1U + /* 240 */ , 0x0471a4ddU, 0x7ae3e578U, 0x0923cb92U, 0x77b18a37U, 0x1ed57a43U, 0x60473be6U, 0x1387150cU, 0x6d1554a9U + /* 248 */ , 0xc14ff5e5U, 0xbfddb440U, 0xcc1d9aaaU, 0xb28fdb0fU, 0xdbeb2b7bU, 0xa5796adeU, 0xd6b94434U, 0xa82b0591U + } + , + /* CRC32C table 7 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xb8aa45ddU, 0x812367bfU, 0x39892262U, 0xf331227bU, 0x4b9b67a6U, 0x721245c4U, 0xcab80019U + /* 8 */ , 0xe66344f6U, 0x5ec9012bU, 0x67402349U, 0xdfea6694U, 0x1552668dU, 0xadf82350U, 0x94710132U, 0x2cdb44efU + /* 16 */ , 0x3db164e9U, 0x851b2134U, 0xbc920356U, 0x0438468bU, 0xce804692U, 0x762a034fU, 0x4fa3212dU, 0xf70964f0U + /* 24 */ , 0xdbd2201fU, 0x637865c2U, 0x5af147a0U, 0xe25b027dU, 0x28e30264U, 0x904947b9U, 0xa9c065dbU, 0x116a2006U + /* 32 */ , 0x8b1425d7U, 0x33be600aU, 0x0a374268U, 0xb29d07b5U, 0x782507acU, 0xc08f4271U, 0xf9066013U, 0x41ac25ceU + /* 40 */ , 0x6d776121U, 0xd5dd24fcU, 0xec54069eU, 0x54fe4343U, 0x9e46435aU, 0x26ec0687U, 0x1f6524e5U, 0xa7cf6138U + /* 48 */ , 0xb6a5413eU, 0x0e0f04e3U, 0x37862681U, 0x8f2c635cU, 0x45946345U, 0xfd3e2698U, 0xc4b704faU, 0x7c1d4127U + /* 56 */ , 0x50c605c8U, 0xe86c4015U, 0xd1e56277U, 0x694f27aaU, 0xa3f727b3U, 0x1b5d626eU, 0x22d4400cU, 0x9a7e05d1U + /* 64 */ , 0xe75fa6abU, 0x5ff5e376U, 0x667cc114U, 0xded684c9U, 0x146e84d0U, 0xacc4c10dU, 0x954de36fU, 0x2de7a6b2U + /* 72 */ , 0x013ce25dU, 0xb996a780U, 0x801f85e2U, 0x38b5c03fU, 0xf20dc026U, 0x4aa785fbU, 0x732ea799U, 0xcb84e244U + /* 80 */ , 0xdaeec242U, 0x6244879fU, 0x5bcda5fdU, 0xe367e020U, 0x29dfe039U, 0x9175a5e4U, 0xa8fc8786U, 0x1056c25bU + /* 88 */ , 0x3c8d86b4U, 0x8427c369U, 0xbdaee10bU, 0x0504a4d6U, 0xcfbca4cfU, 0x7716e112U, 0x4e9fc370U, 0xf63586adU + /* 96 */ , 0x6c4b837cU, 0xd4e1c6a1U, 0xed68e4c3U, 0x55c2a11eU, 0x9f7aa107U, 0x27d0e4daU, 0x1e59c6b8U, 0xa6f38365U + /* 104 */ , 0x8a28c78aU, 0x32828257U, 0x0b0ba035U, 0xb3a1e5e8U, 0x7919e5f1U, 0xc1b3a02cU, 0xf83a824eU, 0x4090c793U + /* 112 */ , 0x51fae795U, 0xe950a248U, 0xd0d9802aU, 0x6873c5f7U, 0xa2cbc5eeU, 0x1a618033U, 0x23e8a251U, 0x9b42e78cU + /* 120 */ , 0xb799a363U, 0x0f33e6beU, 0x36bac4dcU, 0x8e108101U, 0x44a88118U, 0xfc02c4c5U, 0xc58be6a7U, 0x7d21a37aU + /* 128 */ , 0x3fc9a052U, 0x8763e58fU, 0xbeeac7edU, 0x06408230U, 0xccf88229U, 0x7452c7f4U, 0x4ddbe596U, 0xf571a04bU + /* 136 */ , 0xd9aae4a4U, 0x6100a179U, 0x5889831bU, 0xe023c6c6U, 0x2a9bc6dfU, 0x92318302U, 0xabb8a160U, 0x1312e4bdU + /* 144 */ , 0x0278c4bbU, 0xbad28166U, 0x835ba304U, 0x3bf1e6d9U, 0xf149e6c0U, 0x49e3a31dU, 0x706a817fU, 0xc8c0c4a2U + /* 152 */ , 0xe41b804dU, 0x5cb1c590U, 0x6538e7f2U, 0xdd92a22fU, 0x172aa236U, 0xaf80e7ebU, 0x9609c589U, 0x2ea38054U + /* 160 */ , 0xb4dd8585U, 0x0c77c058U, 0x35fee23aU, 0x8d54a7e7U, 0x47eca7feU, 0xff46e223U, 0xc6cfc041U, 0x7e65859cU + /* 168 */ , 0x52bec173U, 0xea1484aeU, 0xd39da6ccU, 0x6b37e311U, 0xa18fe308U, 0x1925a6d5U, 0x20ac84b7U, 0x9806c16aU + /* 176 */ , 0x896ce16cU, 0x31c6a4b1U, 0x084f86d3U, 0xb0e5c30eU, 0x7a5dc317U, 0xc2f786caU, 0xfb7ea4a8U, 0x43d4e175U + /* 184 */ , 0x6f0fa59aU, 0xd7a5e047U, 0xee2cc225U, 0x568687f8U, 0x9c3e87e1U, 0x2494c23cU, 0x1d1de05eU, 0xa5b7a583U + /* 192 */ , 0xd89606f9U, 0x603c4324U, 0x59b56146U, 0xe11f249bU, 0x2ba72482U, 0x930d615fU, 0xaa84433dU, 0x122e06e0U + /* 200 */ , 0x3ef5420fU, 0x865f07d2U, 0xbfd625b0U, 0x077c606dU, 0xcdc46074U, 0x756e25a9U, 0x4ce707cbU, 0xf44d4216U + /* 208 */ , 0xe5276210U, 0x5d8d27cdU, 0x640405afU, 0xdcae4072U, 0x1616406bU, 0xaebc05b6U, 0x973527d4U, 0x2f9f6209U + /* 216 */ , 0x034426e6U, 0xbbee633bU, 0x82674159U, 0x3acd0484U, 0xf075049dU, 0x48df4140U, 0x71566322U, 0xc9fc26ffU + /* 224 */ , 0x5382232eU, 0xeb2866f3U, 0xd2a14491U, 0x6a0b014cU, 0xa0b30155U, 0x18194488U, 0x219066eaU, 0x993a2337U + /* 232 */ , 0xb5e167d8U, 0x0d4b2205U, 0x34c20067U, 0x8c6845baU, 0x46d045a3U, 0xfe7a007eU, 0xc7f3221cU, 0x7f5967c1U + /* 240 */ , 0x6e3347c7U, 0xd699021aU, 0xef102078U, 0x57ba65a5U, 0x9d0265bcU, 0x25a82061U, 0x1c210203U, 0xa48b47deU + /* 248 */ , 0x88500331U, 0x30fa46ecU, 0x0973648eU, 0xb1d92153U, 0x7b61214aU, 0xc3cb6497U, 0xfa4246f5U, 0x42e80328U + } + #endif + }; juint* StubRoutines::ppc64::_constants = StubRoutines::ppc64::generate_crc_constants(); diff --git a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp index ab87c204018..beefd27a4fe 100644 --- a/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/templateInterpreterGenerator_ppc.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015, 2017 SAP SE. All rights reserved. + * Copyright (c) 2015, 2017, SAP SE. 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 @@ -643,12 +643,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch return entry; } -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - address entry = __ pc(); - __ unimplemented("generate_continuation_for"); - return entry; -} - // This entry is returned to when a call returns to the interpreter. // When we arrive here, we expect that the callee stack frame is already popped. address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { @@ -692,6 +686,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, #endif __ sldi(size, size, Interpreter::logStackElementSize); __ add(R15_esp, R15_esp, size); + + __ check_and_handle_popframe(R11_scratch1); + __ check_and_handle_earlyret(R11_scratch1); + __ dispatch_next(state, step); return entry; } @@ -1894,7 +1892,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { __ lwz(crc, 2*wordSize, argP); // Current crc state, zero extend to 64 bit to have a clean register. StubRoutines::ppc64::generate_load_crc_table_addr(_masm, table); - __ kernel_crc32_singleByte(crc, data, dataLen, table, tmp); + __ kernel_crc32_singleByte(crc, data, dataLen, table, tmp, true); // Restore caller sp for c2i case and return. __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started. @@ -1910,7 +1908,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { return NULL; } -// CRC32 Intrinsics. + /** * Method entry for static native methods: * int java.util.zip.CRC32.updateBytes( int crc, byte[] b, int off, int len) @@ -1986,7 +1984,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI // Performance measurements show the 1word and 2word variants to be almost equivalent, // with very light advantages for the 1word variant. We chose the 1word variant for // code compactness. - __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, tc3); + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, tc3, true); // Restore caller sp for c2i case and return. __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started. @@ -2002,8 +2000,88 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI return NULL; } -// Not supported + +/** + * Method entry for intrinsic-candidate (non-native) methods: + * int java.util.zip.CRC32C.updateBytes( int crc, byte[] b, int off, int end) + * int java.util.zip.CRC32C.updateDirectByteBuffer(int crc, long* buf, int off, int end) + * Unlike CRC32, CRC32C does not have any methods marked as native + * CRC32C also uses an "end" variable instead of the length variable CRC32 uses + **/ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { + if (UseCRC32CIntrinsics) { + address start = __ pc(); // Remember stub start address (is rtn value). + + // We don't generate local frame and don't align stack because + // we not even call stub code (we generate the code inline) + // and there is no safepoint on this path. + + // Load parameters. + // Z_esp is callers operand stack pointer, i.e. it points to the parameters. + const Register argP = R15_esp; + const Register crc = R3_ARG1; // crc value + const Register data = R4_ARG2; // address of java byte array + const Register dataLen = R5_ARG3; // source data len + const Register table = R6_ARG4; // address of crc32c table + + const Register t0 = R9; // scratch registers for crc calculation + const Register t1 = R10; + const Register t2 = R11; + const Register t3 = R12; + + const Register tc0 = R2; // registers to hold pre-calculated column addresses + const Register tc1 = R7; + const Register tc2 = R8; + const Register tc3 = table; // table address is reconstructed at the end of kernel_crc32_* emitters + + const Register tmp = t0; // Only used very locally to calculate byte buffer address. + + // Arguments are reversed on java expression stack. + // Calculate address of start element. + if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { // Used for "updateDirectByteBuffer". + BLOCK_COMMENT("CRC32C_updateDirectByteBuffer {"); + // crc @ (SP + 5W) (32bit) + // buf @ (SP + 3W) (64bit ptr to long array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + __ ld( data, 3*wordSize, argP); // start of byte buffer + __ lwa( tmp, 2*wordSize, argP); // byte buffer offset + __ lwa( dataLen, 1*wordSize, argP); // #bytes to process + __ lwz( crc, 5*wordSize, argP); // current crc state + __ add( data, data, tmp); // Add byte buffer offset. + __ sub( dataLen, dataLen, tmp); // (end_index - offset) + } else { // Used for "updateBytes update". + BLOCK_COMMENT("CRC32C_updateBytes {"); + // crc @ (SP + 4W) (32bit) + // buf @ (SP + 3W) (64bit ptr to byte array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + base_offset + __ ld( data, 3*wordSize, argP); // start of byte buffer + __ lwa( tmp, 2*wordSize, argP); // byte buffer offset + __ lwa( dataLen, 1*wordSize, argP); // #bytes to process + __ add( data, data, tmp); // add byte buffer offset + __ sub( dataLen, dataLen, tmp); // (end_index - offset) + __ lwz( crc, 4*wordSize, argP); // current crc state + __ addi(data, data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); + } + + StubRoutines::ppc64::generate_load_crc32c_table_addr(_masm, table); + + // Performance measurements show the 1word and 2word variants to be almost equivalent, + // with very light advantages for the 1word variant. We chose the 1word variant for + // code compactness. + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, tc0, tc1, tc2, tc3, false); + + // Restore caller sp for c2i case and return. + __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started. + __ blr(); + + BLOCK_COMMENT("} CRC32C_update{Bytes|DirectByteBuffer}"); + return start; + } + return NULL; } diff --git a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp index 517a304d4e3..43f6ad1c591 100644 --- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2013, 2016 SAP SE. All rights reserved. + * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017 SAP SE. 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 @@ -1472,13 +1472,13 @@ void TemplateTable::convert() { case Bytecodes::_i2d: __ extsw(R17_tos, R17_tos); case Bytecodes::_l2d: - __ push_l_pop_d(); + __ move_l_to_d(); __ fcfid(F15_ftos, F15_ftos); break; case Bytecodes::_i2f: __ extsw(R17_tos, R17_tos); - __ push_l_pop_d(); + __ move_l_to_d(); if (VM_Version::has_fcfids()) { // fcfids is >= Power7 only // Comment: alternatively, load with sign extend could be done by lfiwax. __ fcfids(F15_ftos, F15_ftos); @@ -1490,7 +1490,7 @@ void TemplateTable::convert() { case Bytecodes::_l2f: if (VM_Version::has_fcfids()) { // fcfids is >= Power7 only - __ push_l_pop_d(); + __ move_l_to_d(); __ fcfids(F15_ftos, F15_ftos); } else { // Avoid rounding problem when result should be 0x3f800001: need fixup code before fcfid+frsp. @@ -1514,7 +1514,7 @@ void TemplateTable::convert() { __ li(R17_tos, 0); // 0 in case of NAN __ bso(CCR0, done); __ fctiwz(F15_ftos, F15_ftos); - __ push_d_pop_l(); + __ move_d_to_l(); break; case Bytecodes::_d2l: @@ -1523,7 +1523,7 @@ void TemplateTable::convert() { __ li(R17_tos, 0); // 0 in case of NAN __ bso(CCR0, done); __ fctidz(F15_ftos, F15_ftos); - __ push_d_pop_l(); + __ move_d_to_l(); break; default: ShouldNotReachHere(); @@ -3660,11 +3660,9 @@ void TemplateTable::_new() { __ cmpdi(CCR0, Rtags, JVM_CONSTANT_Class); __ bne(CCR0, Lslow_case); - // Get instanceKlass (load from Rcpool + sizeof(ConstantPool) + Rindex*BytesPerWord). + // Get instanceKlass __ sldi(Roffset, Rindex, LogBytesPerWord); - __ addi(Rscratch, Rcpool, sizeof(ConstantPool)); - __ isync(); // Order load of instance Klass wrt. tags. - __ ldx(RinstanceKlass, Roffset, Rscratch); + __ load_resolved_klass_at_offset(Rcpool, Roffset, RinstanceKlass); // Make sure klass is fully initialized and get instance_size. __ lbz(Rscratch, in_bytes(InstanceKlass::init_state_offset()), RinstanceKlass); @@ -3722,7 +3720,7 @@ void TemplateTable::_new() { __ bge(CCR0, Lslow_case); // Increment waste limit to prevent getting stuck on this slow path. - __ addi(RtlabWasteLimitValue, RtlabWasteLimitValue, (int)ThreadLocalAllocBuffer::refill_waste_limit_increment()); + __ add_const_optimized(RtlabWasteLimitValue, RtlabWasteLimitValue, ThreadLocalAllocBuffer::refill_waste_limit_increment()); __ std(RtlabWasteLimitValue, in_bytes(JavaThread::tlab_refill_waste_limit_offset()), R16_thread); } // else: No allocation in the shared eden. // fallthru: __ b(Lslow_case); @@ -3875,9 +3873,7 @@ void TemplateTable::checkcast() { // Extract target class from constant pool. __ bind(Lquicked); __ sldi(Roffset, Roffset, LogBytesPerWord); - __ addi(Rcpool, Rcpool, sizeof(ConstantPool)); - __ isync(); // Order load of specified Klass wrt. tags. - __ ldx(RspecifiedKlass, Rcpool, Roffset); + __ load_resolved_klass_at_offset(Rcpool, Roffset, RspecifiedKlass); // Do the checkcast. __ bind(Lresolved); @@ -3939,9 +3935,7 @@ void TemplateTable::instanceof() { // Extract target class from constant pool. __ bind(Lquicked); __ sldi(Roffset, Roffset, LogBytesPerWord); - __ addi(Rcpool, Rcpool, sizeof(ConstantPool)); - __ isync(); // Order load of specified Klass wrt. tags. - __ ldx(RspecifiedKlass, Rcpool, Roffset); + __ load_resolved_klass_at_offset(Rcpool, Roffset, RspecifiedKlass); // Do the checkcast. __ bind(Lresolved); diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp index 5e8be1425fa..4db0a9c20cb 100644 --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, SAP SE. 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 @@ -28,9 +28,11 @@ #include "asm/macroAssembler.inline.hpp" #include "compiler/disassembler.hpp" #include "memory/resourceArea.hpp" +#include "prims/jvm.h" #include "runtime/java.hpp" #include "runtime/os.hpp" #include "runtime/stubCodeGenerator.hpp" +#include "utilities/align.hpp" #include "utilities/defaultStream.hpp" #include "utilities/globalDefinitions.hpp" #include "vm_version_ppc.hpp" @@ -79,7 +81,7 @@ void VM_Version::initialize() { UINTX_FORMAT " on this machine", PowerArchitecturePPC64); // Power 8: Configure Data Stream Control Register. - if (has_mfdscr()) { + if (PowerArchitecturePPC64 >= 8 && has_mfdscr()) { config_dscr(); } @@ -111,7 +113,7 @@ void VM_Version::initialize() { // Create and print feature-string. char buf[(num_features+1) * 16]; // Max 16 chars per feature. jio_snprintf(buf, sizeof(buf), - "ppc64%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + "ppc64%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", (has_fsqrt() ? " fsqrt" : ""), (has_isel() ? " isel" : ""), (has_lxarxeh() ? " lxarxeh" : ""), @@ -126,7 +128,9 @@ void VM_Version::initialize() { (has_vpmsumb() ? " vpmsumb" : ""), (has_tcheck() ? " tcheck" : ""), (has_mfdscr() ? " mfdscr" : ""), - (has_vsx() ? " vsx" : "") + (has_vsx() ? " vsx" : ""), + (has_ldbrx() ? " ldbrx" : ""), + (has_stdbrx() ? " stdbrx" : "") // Make sure number of %s matches num_features! ); _features_string = os::strdup(buf); @@ -172,18 +176,27 @@ void VM_Version::initialize() { assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); - // Implementation does not use any of the vector instructions - // available with Power8. Their exploitation is still pending. + // If defined(VM_LITTLE_ENDIAN) and running on Power8 or newer hardware, + // the implementation uses the vector instructions available with Power8. + // In all other cases, the implementation uses only generally available instructions. if (!UseCRC32Intrinsics) { if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { FLAG_SET_DEFAULT(UseCRC32Intrinsics, true); } } - if (UseCRC32CIntrinsics) { - if (!FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) - warning("CRC32C intrinsics are not available on this CPU"); - FLAG_SET_DEFAULT(UseCRC32CIntrinsics, false); + // Implementation does not use any of the vector instructions available with Power8. + // Their exploitation is still pending (aka "work in progress"). + if (!UseCRC32CIntrinsics) { + if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) { + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true); + } + } + + // TODO: Provide implementation. + if (UseAdler32Intrinsics) { + warning("Adler32Intrinsics not available on this CPU."); + FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); } // The AES intrinsic stubs require AES instruction support. @@ -245,11 +258,6 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } - if (UseAdler32Intrinsics) { - warning("Adler32Intrinsics not available on this CPU."); - FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); - } - if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { UseMultiplyToLenIntrinsic = true; } @@ -319,18 +327,6 @@ void VM_Version::initialize() { // high lock contention. For now we do not use it by default. vm_exit_during_initialization("UseRTMLocking flag should be only set on command line"); } - if (!is_power_of_2(RTMTotalCountIncrRate)) { - warning("RTMTotalCountIncrRate must be a power of 2, resetting it to 64"); - FLAG_SET_DEFAULT(RTMTotalCountIncrRate, 64); - } - if (RTMAbortRatio < 0 || RTMAbortRatio > 100) { - warning("RTMAbortRatio must be in the range 0 to 100, resetting it to 50"); - FLAG_SET_DEFAULT(RTMAbortRatio, 50); - } - if (RTMSpinLoopCount < 0) { - warning("RTMSpinLoopCount must not be a negative value, resetting it to 0"); - FLAG_SET_DEFAULT(RTMSpinLoopCount, 0); - } #else // Only C2 does RTM locking optimization. // Can't continue because UseRTMLocking affects UseBiasedLocking flag @@ -659,6 +655,8 @@ void VM_Version::determine_features() { a->tcheck(0); // code[12] -> tcheck a->mfdscr(R0); // code[13] -> mfdscr a->lxvd2x(VSR0, R3_ARG1); // code[14] -> vsx + a->ldbrx(R7, R3_ARG1, R4_ARG2); // code[15] -> ldbrx + a->stdbrx(R7, R3_ARG1, R4_ARG2); // code[16] -> stdbrx a->blr(); // Emit function to set one cache line to zero. Emit function descriptor and get pointer to it. @@ -688,7 +686,7 @@ void VM_Version::determine_features() { // Execute code. Illegal instructions will be replaced by 0 in the signal handler. VM_Version::_is_determine_features_test_running = true; // We must align the first argument to 16 bytes because of the lqarx check. - (*test)((address)align_size_up((intptr_t)mid_of_test_area, 16), (uint64_t)0); + (*test)(align_up((address)mid_of_test_area, 16), 0); VM_Version::_is_determine_features_test_running = false; // determine which instructions are legal. @@ -708,6 +706,8 @@ void VM_Version::determine_features() { if (code[feature_cntr++]) features |= tcheck_m; if (code[feature_cntr++]) features |= mfdscr_m; if (code[feature_cntr++]) features |= vsx_m; + if (code[feature_cntr++]) features |= ldbrx_m; + if (code[feature_cntr++]) features |= stdbrx_m; // Print the detection code. if (PrintAssembly) { diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp index 2d1f8db990e..f7d5ea73aca 100644 --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2016 SAP SE. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017 SAP SE. 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 @@ -47,6 +47,8 @@ protected: tcheck, mfdscr, vsx, + ldbrx, + stdbrx, num_features // last entry to count features }; enum Feature_Flag_Set { @@ -66,6 +68,8 @@ protected: tcheck_m = (1 << tcheck ), mfdscr_m = (1 << mfdscr ), vsx_m = (1 << vsx ), + ldbrx_m = (1 << ldbrx ), + stdbrx_m = (1 << stdbrx ), all_features_m = (unsigned long)-1 }; @@ -100,6 +104,9 @@ public: static bool has_tcheck() { return (_features & tcheck_m) != 0; } static bool has_mfdscr() { return (_features & mfdscr_m) != 0; } static bool has_vsx() { return (_features & vsx_m) != 0; } + static bool has_ldbrx() { return (_features & ldbrx_m) != 0; } + static bool has_stdbrx() { return (_features & stdbrx_m) != 0; } + static bool has_mtfprd() { return has_vpmsumb(); } // alias for P8 // Assembler testing static void allow_all(); diff --git a/hotspot/src/cpu/s390/vm/abstractInterpreter_s390.cpp b/hotspot/src/cpu/s390/vm/abstractInterpreter_s390.cpp index 2140ac711a6..ab6139c1354 100644 --- a/hotspot/src/cpu/s390/vm/abstractInterpreter_s390.cpp +++ b/hotspot/src/cpu/s390/vm/abstractInterpreter_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -51,11 +51,6 @@ int AbstractInterpreter::BasicType_as_index(BasicType type) { return i; } -bool AbstractInterpreter::can_be_compiled(methodHandle m) { - // No special entry points that preclude compilation. - return true; -} - // How much stack a method top interpreter activation needs in words. int AbstractInterpreter::size_top_interpreter_activation(Method* method) { diff --git a/hotspot/src/cpu/s390/vm/assembler_s390.hpp b/hotspot/src/cpu/s390/vm/assembler_s390.hpp index 0873d71b00e..8a7ae9d0756 100644 --- a/hotspot/src/cpu/s390/vm/assembler_s390.hpp +++ b/hotspot/src/cpu/s390/vm/assembler_s390.hpp @@ -28,8 +28,6 @@ #undef LUCY_DBG -#define NearLabel Label - // Immediate is an abstraction to represent the various immediate // operands which exist on z/Architecture. Neither this class nor // instances hereof have an own state. It consists of methods only. diff --git a/hotspot/src/cpu/s390/vm/bytes_s390.hpp b/hotspot/src/cpu/s390/vm/bytes_s390.hpp index 6209624d335..f01ea07a2e2 100644 --- a/hotspot/src/cpu/s390/vm/bytes_s390.hpp +++ b/hotspot/src/cpu/s390/vm/bytes_s390.hpp @@ -42,12 +42,6 @@ class Bytes: AllStatic { // // In short, it makes no sense on z/Architecture to piecemeal get or put unaligned data. - // Returns true if the byte ordering used by Java is different from - // the native byte ordering of the underlying machine. - // z/Arch is big endian, thus, a swap between native and Java ordering - // is always a no-op. - static inline bool is_Java_byte_ordering_different() { return false; } - // Only swap on little endian machines => suffix `_le'. static inline u2 swap_u2_le(u2 x) { return x; } static inline u4 swap_u4_le(u4 x) { return x; } diff --git a/hotspot/src/cpu/s390/vm/c1_CodeStubs_s390.cpp b/hotspot/src/cpu/s390/vm/c1_CodeStubs_s390.cpp index 4d429960798..ec6517894b9 100644 --- a/hotspot/src/cpu/s390/vm/c1_CodeStubs_s390.cpp +++ b/hotspot/src/cpu/s390/vm/c1_CodeStubs_s390.cpp @@ -31,6 +31,7 @@ #include "c1/c1_Runtime1.hpp" #include "nativeInst_s390.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/align.hpp" #include "utilities/macros.hpp" #include "vmreg_s390.inline.hpp" #if INCLUDE_ALL_GCS @@ -284,7 +285,7 @@ void PatchingStub::align_patch_site(MacroAssembler* masm) { masm->block_comment(bc); #endif - masm->align(round_to(NativeGeneralJump::instruction_size, wordSize)); + masm->align(align_up((int)NativeGeneralJump::instruction_size, wordSize)); } void PatchingStub::emit_code(LIR_Assembler* ce) { diff --git a/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp b/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp index 84fb4205099..21634f930e7 100644 --- a/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp +++ b/hotspot/src/cpu/s390/vm/c1_LIRAssembler_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. 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 @@ -1139,14 +1139,7 @@ void LIR_Assembler::return_op(LIR_Opr result) { __ load_const_optimized(Z_R1_scratch, pp); // Pop the frame before the safepoint code. - int retPC_offset = initial_frame_size_in_bytes() + _z_abi16(return_pc); - if (Displacement::is_validDisp(retPC_offset)) { - __ z_lg(Z_R14, retPC_offset, Z_SP); - __ add2reg(Z_SP, initial_frame_size_in_bytes()); - } else { - __ add2reg(Z_SP, initial_frame_size_in_bytes()); - __ restore_return_pc(); - } + __ pop_frame_restore_retPC(initial_frame_size_in_bytes()); if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) { __ reserved_stack_check(Z_R14); @@ -3048,9 +3041,8 @@ void LIR_Assembler::emit_updatecrc32(LIR_OpUpdateCRC32* op) { assert_different_registers(val, crc, res); __ load_const_optimized(res, StubRoutines::crc_table_addr()); - __ not_(crc, noreg, false); // ~crc - __ update_byte_crc32(crc, val, res); - __ not_(res, crc, false); // ~crc + __ kernel_crc32_singleByteReg(crc, val, res, true); + __ z_lgfr(res, crc); } #undef __ diff --git a/hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp b/hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp index 0ec97da6230..8ebecadd85c 100644 --- a/hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp +++ b/hotspot/src/cpu/s390/vm/c1_LIRGenerator_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. 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 @@ -61,20 +61,6 @@ void LIRItem::load_nonconstant(int bits) { } } -inline void load_int_as_long(LIR_List *ll, LIRItem &li, LIR_Opr dst) { - LIR_Opr r = li.value()->operand(); - if (r->is_constant()) { - // Constants get loaded with sign extend on this platform. - ll->move(li.result(), dst); - } else { - if (!r->is_register()) { - li.load_item_force(dst); - } - LIR_Opr dst_l = FrameMap::as_long_opr(dst->as_register()); - ll->convert(Bytecodes::_i2l, li.result(), dst_l); // Convert. - } -} - //-------------------------------------------------------------- // LIRGenerator //-------------------------------------------------------------- @@ -1224,10 +1210,9 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { LIR_Opr arg2 = cc->at(1); LIR_Opr arg3 = cc->at(2); - // CCallingConventionRequiresIntsAsLongs crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32 stub doesn't care about high bits. __ leal(LIR_OprFact::address(a), arg2); - load_int_as_long(gen()->lir(), len, arg3); + len.load_item_force(arg3); // We skip int->long conversion here, because CRC32 stub expects int. __ call_runtime_leaf(StubRoutines::updateBytesCRC32(), LIR_OprFact::illegalOpr, result_reg, cc->args()); __ move(result_reg, result); @@ -1240,7 +1225,70 @@ void LIRGenerator::do_update_CRC32(Intrinsic* x) { } void LIRGenerator::do_update_CRC32C(Intrinsic* x) { - Unimplemented(); + assert(UseCRC32CIntrinsics, "or should not be here"); + LIR_Opr result = rlock_result(x); + + switch (x->id()) { + case vmIntrinsics::_updateBytesCRC32C: + case vmIntrinsics::_updateDirectByteBufferCRC32C: { + bool is_updateBytes = (x->id() == vmIntrinsics::_updateBytesCRC32C); + + LIRItem crc(x->argument_at(0), this); + LIRItem buf(x->argument_at(1), this); + LIRItem off(x->argument_at(2), this); + LIRItem end(x->argument_at(3), this); + buf.load_item(); + off.load_nonconstant(); + end.load_nonconstant(); + + // len = end - off + LIR_Opr len = end.result(); + LIR_Opr tmpA = new_register(T_INT); + LIR_Opr tmpB = new_register(T_INT); + __ move(end.result(), tmpA); + __ move(off.result(), tmpB); + __ sub(tmpA, tmpB, tmpA); + len = tmpA; + + LIR_Opr index = off.result(); + int offset = is_updateBytes ? arrayOopDesc::base_offset_in_bytes(T_BYTE) : 0; + if (off.result()->is_constant()) { + index = LIR_OprFact::illegalOpr; + offset += off.result()->as_jint(); + } + LIR_Opr base_op = buf.result(); + + if (index->is_valid()) { + LIR_Opr tmp = new_register(T_LONG); + __ convert(Bytecodes::_i2l, index, tmp); + index = tmp; + } + + LIR_Address* a = new LIR_Address(base_op, index, offset, T_BYTE); + + BasicTypeList signature(3); + signature.append(T_INT); + signature.append(T_ADDRESS); + signature.append(T_INT); + CallingConvention* cc = frame_map()->c_calling_convention(&signature); + const LIR_Opr result_reg = result_register_for (x->type()); + + LIR_Opr arg1 = cc->at(0); + LIR_Opr arg2 = cc->at(1); + LIR_Opr arg3 = cc->at(2); + + crc.load_item_force(arg1); // We skip int->long conversion here, because CRC32C stub doesn't care about high bits. + __ leal(LIR_OprFact::address(a), arg2); + __ move(len, cc->at(2)); // We skip int->long conversion here, because CRC32C stub expects int. + + __ call_runtime_leaf(StubRoutines::updateBytesCRC32C(), LIR_OprFact::illegalOpr, result_reg, cc->args()); + __ move(result_reg, result); + break; + } + default: { + ShouldNotReachHere(); + } + } } void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { @@ -1271,4 +1319,3 @@ void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { fatal("vectorizedMismatch intrinsic is not implemented on this platform"); } - diff --git a/hotspot/src/cpu/s390/vm/c1_MacroAssembler_s390.cpp b/hotspot/src/cpu/s390/vm/c1_MacroAssembler_s390.cpp index f7f8c29466a..63bc8c0acf4 100644 --- a/hotspot/src/cpu/s390/vm/c1_MacroAssembler_s390.cpp +++ b/hotspot/src/cpu/s390/vm/c1_MacroAssembler_s390.cpp @@ -70,7 +70,7 @@ void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_by assert(bang_size_in_bytes >= frame_size_in_bytes, "stack bang size incorrect"); generate_stack_overflow_check(bang_size_in_bytes); save_return_pc(); - push_frame(frame_size_in_bytes); // TODO: Must we add z_abi_160? + push_frame(frame_size_in_bytes); } void C1_MacroAssembler::unverified_entry(Register receiver, Register ic_klass) { diff --git a/hotspot/src/cpu/s390/vm/frame_s390.cpp b/hotspot/src/cpu/s390/vm/frame_s390.cpp index bf5cc5fc207..9ba85eb0669 100644 --- a/hotspot/src/cpu/s390/vm/frame_s390.cpp +++ b/hotspot/src/cpu/s390/vm/frame_s390.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -496,6 +496,8 @@ void frame::describe_pd(FrameValues& values, int frame_no) { } } + +void frame::pd_ps() {} #endif // !PRODUCT intptr_t *frame::initial_deoptimization_info() { diff --git a/hotspot/src/cpu/s390/vm/frame_s390.inline.hpp b/hotspot/src/cpu/s390/vm/frame_s390.inline.hpp index 3231daf94d5..11917ac6d53 100644 --- a/hotspot/src/cpu/s390/vm/frame_s390.inline.hpp +++ b/hotspot/src/cpu/s390/vm/frame_s390.inline.hpp @@ -28,6 +28,7 @@ #include "code/codeCache.hpp" #include "code/vmreg.inline.hpp" +#include "utilities/align.hpp" // Inline functions for z/Architecture frames: @@ -241,7 +242,7 @@ inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* monitors) inline int frame::interpreter_frame_monitor_size() { // Number of stack slots for a monitor - return round_to(BasicObjectLock::size() /* number of stack slots */, + return align_up(BasicObjectLock::size() /* number of stack slots */, WordsPerLong /* Number of stack slots for a Java long. */); } diff --git a/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp b/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp index 8cec2da25ac..bdbc7031872 100644 --- a/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp +++ b/hotspot/src/cpu/s390/vm/interp_masm_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017 SAP SE. 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 @@ -107,24 +107,15 @@ void InterpreterMacroAssembler::dispatch_base(TosState state, address* table) { // TODO: Maybe implement +VerifyActivationFrameSize here. // verify_thread(); // Too slow. We will just verify on method entry & exit. verify_oop(Z_tos, state); -#ifdef FAST_DISPATCH - if (table == Interpreter::dispatch_table(state)) { - // Use IdispatchTables. - add(Lbyte_code, Interpreter::distance_from_dispatch_table(state), Lbyte_code); - // Add offset to correct dispatch table. - sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // Multiply by wordSize. - ld_ptr(IdispatchTables, Lbyte_code, G3_scratch); // Get entry addr. - } else -#endif - { - // Dispatch table to use. - load_absolute_address(Z_tmp_1, (address) table); // Z_tmp_1 = table; - // 0 <= Z_bytecode < 256 => Use a 32 bit shift, because it is shorter than sllg. - // Z_bytecode must have been loaded zero-extended for this approach to be correct. - z_sll(Z_bytecode, LogBytesPerWord, Z_R0); // Multiply by wordSize. - z_lg(Z_tmp_1, 0, Z_bytecode, Z_tmp_1); // Get entry addr. - } + // Dispatch table to use. + load_absolute_address(Z_tmp_1, (address) table); // Z_tmp_1 = table; + + // 0 <= Z_bytecode < 256 => Use a 32 bit shift, because it is shorter than sllg. + // Z_bytecode must have been loaded zero-extended for this approach to be correct. + z_sll(Z_bytecode, LogBytesPerWord, Z_R0); // Multiply by wordSize. + z_lg(Z_tmp_1, 0, Z_bytecode, Z_tmp_1); // Get entry addr. + z_br(Z_tmp_1); } @@ -371,7 +362,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result Register tmp = index; // reuse z_sllg(index, index, LogBytesPerHeapOop); // Offset into resolved references array. // Load pointer for resolved_references[] objArray. - z_lg(result, ConstantPool::resolved_references_offset_in_bytes(), result); + z_lg(result, ConstantPool::cache_offset_in_bytes(), result); + z_lg(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result); // JNIHandles::resolve(result) z_lg(result, 0, result); // Load resolved references array itself. #ifdef ASSERT @@ -386,6 +378,16 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index(Register result load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result); } +// load cpool->resolved_klass_at(index) +void InterpreterMacroAssembler::load_resolved_klass_at_offset(Register cpool, Register offset, Register iklass) { + // int value = *(Rcpool->int_at_addr(which)); + // int resolved_klass_index = extract_low_short_from_int(value); + z_llgh(offset, Address(cpool, offset, sizeof(ConstantPool) + 2)); // offset = resolved_klass_index (s390 is big-endian) + z_sllg(offset, offset, LogBytesPerWord); // Convert 'index' to 'offset' + z_lg(iklass, Address(cpool, ConstantPool::resolved_klasses_offset_in_bytes())); // iklass = cpool->_resolved_klasses + z_lg(iklass, Address(iklass, offset, Array::base_offset_in_bytes())); +} + void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, diff --git a/hotspot/src/cpu/s390/vm/interp_masm_s390.hpp b/hotspot/src/cpu/s390/vm/interp_masm_s390.hpp index 5f29a606481..bebbb4a7445 100644 --- a/hotspot/src/cpu/s390/vm/interp_masm_s390.hpp +++ b/hotspot/src/cpu/s390/vm/interp_masm_s390.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017 SAP SE. 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 @@ -48,9 +48,6 @@ class InterpreterMacroAssembler: public MacroAssembler { bool allow_relocation, bool check_exceptions); - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - // Base routine for all dispatches. void dispatch_base(TosState state, address* table); @@ -58,6 +55,9 @@ class InterpreterMacroAssembler: public MacroAssembler { InterpreterMacroAssembler(CodeBuffer* c) : MacroAssembler(c) {} + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + void jump_to_entry(address entry, Register Rscratch); virtual void load_earlyret_value(TosState state); @@ -115,6 +115,8 @@ class InterpreterMacroAssembler: public MacroAssembler { void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2)); void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2)); void load_resolved_reference_at_index(Register result, Register index); + // load cpool->resolved_klass_at(index) + void load_resolved_klass_at_offset(Register cpool, Register offset, Register iklass); // Pop topmost element from stack. It just disappears. Useful if // consumed previously by access via stackTop(). diff --git a/hotspot/src/cpu/s390/vm/interpreterRT_s390.hpp b/hotspot/src/cpu/s390/vm/interpreterRT_s390.hpp index 67e3b914c34..9a938b2c537 100644 --- a/hotspot/src/cpu/s390/vm/interpreterRT_s390.hpp +++ b/hotspot/src/cpu/s390/vm/interpreterRT_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -51,7 +51,7 @@ class SignatureHandlerGenerator: public NativeSignatureIterator { public: // creation - SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) { + SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) { _masm = new MacroAssembler(buffer); _fp_arg_nr = 0; } diff --git a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp index d5776117436..c14d596223d 100644 --- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp +++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. 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 @@ -1616,6 +1616,8 @@ void MacroAssembler::branch_optimized(Assembler::branch_condition cond, Label& b if (branch_target.is_bound()) { address branch_addr = target(branch_target); branch_optimized(cond, branch_addr); + } else if (branch_target.is_near()) { + z_brc(cond, branch_target); // Caller assures that the target will be in range for z_brc. } else { z_brcl(cond, branch_target); // Let's hope target is in range. Otherwise, we will abort at patch time. } @@ -1674,7 +1676,8 @@ void MacroAssembler::compare_and_branch_optimized(Register r1, bool has_sign) { address branch_origin = pc(); bool x2_imm8 = (has_sign && Immediate::is_simm8(x2)) || (!has_sign && Immediate::is_uimm8(x2)); - bool is_RelAddr16 = (branch_target.is_bound() && + bool is_RelAddr16 = branch_target.is_near() || + (branch_target.is_bound() && RelAddr::is_in_range_of_RelAddr16(target(branch_target), branch_origin)); unsigned int casenum = (len64?2:0)+(has_sign?0:1); @@ -1744,13 +1747,21 @@ void MacroAssembler::compare_and_branch_optimized(Register r1, Label& branch_target, bool len64, bool has_sign) { - unsigned int casenum = (len64?2:0)+(has_sign?0:1); + unsigned int casenum = (len64 ? 2 : 0) + (has_sign ? 0 : 1); if (branch_target.is_bound()) { address branch_addr = target(branch_target); compare_and_branch_optimized(r1, r2, cond, branch_addr, len64, has_sign); } else { - { + if (VM_Version::has_CompareBranch() && branch_target.is_near()) { + switch (casenum) { + case 0: z_crj( r1, r2, cond, branch_target); break; + case 1: z_clrj( r1, r2, cond, branch_target); break; + case 2: z_cgrj( r1, r2, cond, branch_target); break; + case 3: z_clgrj(r1, r2, cond, branch_target); break; + default: ShouldNotReachHere(); break; + } + } else { switch (casenum) { case 0: z_cr( r1, r2); break; case 1: z_clr(r1, r2); break; @@ -2011,17 +2022,41 @@ void MacroAssembler::resize_frame_sub(Register offset, Register fp, bool load_fp z_stg(fp, _z_abi(callers_sp), Z_SP); } -// Resize_frame with SP(new) = [addr]. -void MacroAssembler::resize_frame_absolute(Register addr, Register fp, bool load_fp) { - assert_different_registers(addr, fp, Z_SP); - if (load_fp) { z_lg(fp, _z_abi(callers_sp), Z_SP); } +// Resize_frame with SP(new) = [newSP] + offset. +// This emitter is useful if we already have calculated a pointer +// into the to-be-allocated stack space, e.g. with special alignment properties, +// but need some additional space, e.g. for spilling. +// newSP is the pre-calculated pointer. It must not be modified. +// fp holds, or is filled with, the frame pointer. +// offset is the additional increment which is added to addr to form the new SP. +// Note: specify a negative value to reserve more space! +// load_fp == true only indicates that fp is not pre-filled with the frame pointer. +// It does not guarantee that fp contains the frame pointer at the end. +void MacroAssembler::resize_frame_abs_with_offset(Register newSP, Register fp, int offset, bool load_fp) { + assert_different_registers(newSP, fp, Z_SP); - if (addr != Z_R0) { - // Minimize stalls by not using Z_SP immediately after update. - z_stg(fp, _z_abi(callers_sp), addr); - z_lgr(Z_SP, addr); + if (load_fp) { + z_lg(fp, _z_abi(callers_sp), Z_SP); + } + + add2reg(Z_SP, offset, newSP); + z_stg(fp, _z_abi(callers_sp), Z_SP); +} + +// Resize_frame with SP(new) = [newSP]. +// load_fp == true only indicates that fp is not pre-filled with the frame pointer. +// It does not guarantee that fp contains the frame pointer at the end. +void MacroAssembler::resize_frame_absolute(Register newSP, Register fp, bool load_fp) { + assert_different_registers(newSP, fp, Z_SP); + + if (load_fp) { + z_lg(fp, _z_abi(callers_sp), Z_SP); // need to use load/store. + } + + z_lgr(Z_SP, newSP); + if (newSP != Z_R0) { // make sure we generate correct code, no matter what register newSP uses. + z_stg(fp, _z_abi(callers_sp), newSP); } else { - z_lgr(Z_SP, addr); z_stg(fp, _z_abi(callers_sp), Z_SP); } } @@ -2029,17 +2064,12 @@ void MacroAssembler::resize_frame_absolute(Register addr, Register fp, bool load // Resize_frame with SP(new) = SP(old) + offset. void MacroAssembler::resize_frame(RegisterOrConstant offset, Register fp, bool load_fp) { assert_different_registers(fp, Z_SP); - if (load_fp) z_lg(fp, _z_abi(callers_sp), Z_SP); - if (Displacement::is_validDisp((int)_z_abi(callers_sp) + offset.constant_or_zero())) { - // Minimize stalls by first using, then updating Z_SP. - // Do that only if we have a small positive offset or if ExtImm are available. - z_stg(fp, Address(Z_SP, offset, _z_abi(callers_sp))); - add64(Z_SP, offset); - } else { - add64(Z_SP, offset); - z_stg(fp, _z_abi(callers_sp), Z_SP); + if (load_fp) { + z_lg(fp, _z_abi(callers_sp), Z_SP); } + add64(Z_SP, offset); + z_stg(fp, _z_abi(callers_sp), Z_SP); } void MacroAssembler::push_frame(Register bytes, Register old_sp, bool copy_sp, bool bytes_with_inverted_sign) { @@ -2052,32 +2082,32 @@ void MacroAssembler::push_frame(Register bytes, Register old_sp, bool copy_sp, b #endif if (copy_sp) { z_lgr(old_sp, Z_SP); } if (bytes_with_inverted_sign) { - z_stg(old_sp, 0, bytes, Z_SP); - add2reg_with_index(Z_SP, 0, bytes, Z_SP); + z_agr(Z_SP, bytes); } else { z_sgr(Z_SP, bytes); // Z_sgfr sufficient, but probably not faster. - z_stg(old_sp, 0, Z_SP); } + z_stg(old_sp, _z_abi(callers_sp), Z_SP); } unsigned int MacroAssembler::push_frame(unsigned int bytes, Register scratch) { long offset = Assembler::align(bytes, frame::alignment_in_bytes); + assert(offset > 0, "should push a frame with positive size, size = %ld.", offset); + assert(Displacement::is_validDisp(-offset), "frame size out of range, size = %ld", offset); - if (Displacement::is_validDisp(-offset)) { - // Minimize stalls by first using, then updating Z_SP. - // Do that only if we have ExtImm available. - z_stg(Z_SP, -offset, Z_SP); - add2reg(Z_SP, -offset); - } else { - if (scratch != Z_R0 && scratch != Z_R1) { - z_stg(Z_SP, -offset, Z_SP); - add2reg(Z_SP, -offset); - } else { // scratch == Z_R0 || scratch == Z_R1 - z_lgr(scratch, Z_SP); - add2reg(Z_SP, -offset); - z_stg(scratch, 0, Z_SP); - } + // We must not write outside the current stack bounds (given by Z_SP). + // Thus, we have to first update Z_SP and then store the previous SP as stack linkage. + // We rely on Z_R0 by default to be available as scratch. + z_lgr(scratch, Z_SP); + add2reg(Z_SP, -offset); + z_stg(scratch, _z_abi(callers_sp), Z_SP); +#ifdef ASSERT + // Just make sure nobody uses the value in the default scratch register. + // When another register is used, the caller might rely on it containing the frame pointer. + if (scratch == Z_R0) { + z_iihf(scratch, 0xbaadbabe); + z_iilf(scratch, 0xdeadbeef); } +#endif return offset; } @@ -2095,6 +2125,20 @@ void MacroAssembler::pop_frame() { Assembler::z_lg(Z_SP, _z_abi(callers_sp), Z_SP); } +// Pop current C frame and restore return PC register (Z_R14). +void MacroAssembler::pop_frame_restore_retPC(int frame_size_in_bytes) { + BLOCK_COMMENT("pop_frame_restore_retPC:"); + int retPC_offset = _z_abi16(return_pc) + frame_size_in_bytes; + // If possible, pop frame by add instead of load (a penny saved is a penny got :-). + if (Displacement::is_validDisp(retPC_offset)) { + z_lg(Z_R14, retPC_offset, Z_SP); + add2reg(Z_SP, frame_size_in_bytes); + } else { + add2reg(Z_SP, frame_size_in_bytes); + restore_return_pc(); + } +} + void MacroAssembler::call_VM_leaf_base(address entry_point, bool allow_relocation) { if (allow_relocation) { call_c(entry_point); @@ -2741,11 +2785,11 @@ void MacroAssembler::lookup_interface_method(Register recv_klass, BLOCK_COMMENT("lookup_interface_method {"); // Load start of itable entries into itable_entry_addr. - z_llgf(vtable_len, Address(recv_klass, InstanceKlass::vtable_length_offset())); + z_llgf(vtable_len, Address(recv_klass, Klass::vtable_length_offset())); z_sllg(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes())); // Loop over all itable entries until desired interfaceOop(Rinterface) found. - const int vtable_base_offset = in_bytes(InstanceKlass::vtable_start_offset()); + const int vtable_base_offset = in_bytes(Klass::vtable_start_offset()); add2reg_with_index(itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(), @@ -3474,6 +3518,17 @@ void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp // Purpose: record the previous value if it is not null. // All non-tmps are preserved. //------------------------------------------------------ +// Note: Rpre_val needs special attention. +// The flag pre_val_needed indicated that the caller of this emitter function +// relies on Rpre_val containing the correct value, that is: +// either the value it contained on entry to this code segment +// or the value that was loaded into the register from (Robj+offset). +// +// Independent from this requirement, the contents of Rpre_val must survive +// the push_frame() operation. push_frame() uses Z_R0_scratch by default +// to temporarily remember the frame pointer. +// If Rpre_val is assigned Z_R0_scratch by the caller, code must be emitted to +// save it's value. void MacroAssembler::g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val, // Ideally, this is a non-volatile register. @@ -3487,6 +3542,16 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj, const int buffer_offset = in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_buf()); const int index_offset = in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_index()); assert_different_registers(Rtmp1, Rtmp2, Z_R0_scratch); // None of the Rtmp must be Z_R0!! + assert_different_registers(Robj, Z_R0_scratch); // Used for addressing. Furthermore, push_frame destroys Z_R0!! + assert_different_registers(Rval, Z_R0_scratch); // push_frame destroys Z_R0!! + +#ifdef ASSERT + // make sure the register is not Z_R0. Used for addressing. Furthermore, would be destroyed by push_frame. + if (offset.is_register() && offset.as_register()->encoding() == 0) { + tty->print_cr("Roffset(g1_write_barrier_pre) = %%r%d", offset.as_register()->encoding()); + assert(false, "bad register for offset"); + } +#endif BLOCK_COMMENT("g1_write_barrier_pre {"); @@ -3500,7 +3565,10 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj, } z_bre(filtered); // Activity indicator is zero, so there is no marking going on currently. - // Do we need to load the previous value into Rpre_val? + assert(Rpre_val != noreg, "must have a real register"); + + + // If an object is given, we need to load the previous value into Rpre_val. if (Robj != noreg) { // Load the previous value... Register ixReg = offset.is_register() ? offset.register_or_noreg() : Z_R0; @@ -3510,9 +3578,9 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj, z_lg(Rpre_val, offset.constant_or_zero(), ixReg, Robj); } } - assert(Rpre_val != noreg, "must have a real register"); // Is the previous value NULL? + // If so, we don't need to record it and we're done. // Note: pre_val is loaded, decompressed and stored (directly or via runtime call). // Register contents is preserved across runtime call if caller requests to do so. z_ltgr(Rpre_val, Rpre_val); @@ -3529,6 +3597,7 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj, // only if index > 0. Otherwise, we need runtime to handle. // (The index field is typed as size_t.) Register Rbuffer = Rtmp1, Rindex = Rtmp2; + assert_different_registers(Rbuffer, Rindex, Rpre_val); z_lg(Rbuffer, buffer_offset, Z_thread); @@ -3547,16 +3616,8 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj, bind(callRuntime); - // Save Rpre_val (result) over runtime call. - // Requires Rtmp1, Rtmp2, or Rpre_val to be non-volatile. - Register Rpre_save = Rpre_val; - if (pre_val_needed && Rpre_val->is_volatile()) { - guarantee(!Rtmp1->is_volatile() || !Rtmp2->is_volatile(), "oops!"); - Rpre_save = !Rtmp1->is_volatile() ? Rtmp1 : Rtmp2; - } - lgr_if_needed(Rpre_save, Rpre_val); - - // Preserve inputs by spilling them into the top frame. + // Save some registers (inputs and result) over runtime call + // by spilling them into the top frame. if (Robj != noreg && Robj->is_volatile()) { z_stg(Robj, Robj->encoding()*BytesPerWord, Z_SP); } @@ -3568,11 +3629,20 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj, z_stg(Rval, Rval->encoding()*BytesPerWord, Z_SP); } + // Save Rpre_val (result) over runtime call. + Register Rpre_save = Rpre_val; + if ((Rpre_val == Z_R0_scratch) || (pre_val_needed && Rpre_val->is_volatile())) { + guarantee(!Rtmp1->is_volatile() || !Rtmp2->is_volatile(), "oops!"); + Rpre_save = !Rtmp1->is_volatile() ? Rtmp1 : Rtmp2; + } + lgr_if_needed(Rpre_save, Rpre_val); + // Push frame to protect top frame with return pc and spilled register values. save_return_pc(); - push_frame_abi160(0); // Will use Z_R0 as tmp on old CPUs. + push_frame_abi160(0); // Will use Z_R0 as tmp. - call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), Rpre_val, Z_thread); + // Rpre_val may be destroyed by push_frame(). + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), Rpre_save, Z_thread); pop_frame(); restore_return_pc(); @@ -3588,9 +3658,9 @@ void MacroAssembler::g1_write_barrier_pre(Register Robj, if (Rval != noreg && Rval->is_volatile()) { z_lg(Rval, Rval->encoding()*BytesPerWord, Z_SP); } - - // Restore Rpre_val (result) after runtime call. - lgr_if_needed(Rpre_val, Rpre_save); + if (pre_val_needed && Rpre_val->is_volatile()) { + lgr_if_needed(Rpre_val, Rpre_save); + } bind(filtered); BLOCK_COMMENT("} g1_write_barrier_pre"); @@ -3643,7 +3713,7 @@ void MacroAssembler::g1_write_barrier_post(Register Rstore_addr, // calculate address of card load_const_optimized(Rbase, (address)bs->byte_map_base); // Card table base. z_srlg(Rcard_addr, Rstore_addr, CardTableModRefBS::card_shift); // Index into card table. - add2reg_with_index(Rcard_addr, 0, Rcard_addr, Rbase); // Explicit calculation needed for cli. + z_algr(Rcard_addr, Rbase); // Explicit calculation needed for cli. Rbase = noreg; // end of lifetime // Filter young. @@ -3687,6 +3757,7 @@ void MacroAssembler::g1_write_barrier_post(Register Rstore_addr, // TODO: do we need a frame? Introduced to be on the safe side. bool needs_frame = true; + lgr_if_needed(Rcard_addr, Rcard_addr_x); // copy back asap. push_frame will destroy Z_R0_scratch! // VM call need frame to access(write) O register. if (needs_frame) { @@ -3695,7 +3766,7 @@ void MacroAssembler::g1_write_barrier_post(Register Rstore_addr, } // Save the live input values. - call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), Rcard_addr_x, Z_thread); + call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), Rcard_addr, Z_thread); if (needs_frame) { pop_frame(); @@ -4051,7 +4122,12 @@ void MacroAssembler::store_klass(Register klass, Register dst_oop, Register ck) void MacroAssembler::store_klass_gap(Register s, Register d) { if (UseCompressedClassPointers) { assert(s != d, "not enough registers"); - z_st(s, Address(d, oopDesc::klass_gap_offset_in_bytes())); + // Support s = noreg. + if (s != noreg) { + z_st(s, Address(d, oopDesc::klass_gap_offset_in_bytes())); + } else { + z_mvhi(Address(d, oopDesc::klass_gap_offset_in_bytes()), 0); + } } } @@ -5927,8 +6003,7 @@ void MacroAssembler::update_byte_crc32(Register crc, Register val, Register tabl * @param len register containing number of bytes * @param table register pointing to CRC table */ -void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, - Register data, bool invertCRC) { +void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, Register data) { assert_different_registers(crc, buf, len, table, data); Label L_mainLoop, L_done; @@ -5938,20 +6013,12 @@ void MacroAssembler::update_byteLoop_crc32(Register crc, Register buf, Register z_ltr(len, len); z_brnh(L_done); - if (invertCRC) { - not_(crc, noreg, false); // ~c - } - bind(L_mainLoop); z_llgc(data, Address(buf, (intptr_t)0));// Current byte of input buffer (zero extended). Avoids garbage in upper half of register. add2reg(buf, mainLoop_stepping); // Advance buffer position. update_byte_crc32(crc, data, table); z_brct(len, L_mainLoop); // Iterate. - if (invertCRC) { - not_(crc, noreg, false); // ~c - } - bind(L_done); } @@ -5968,6 +6035,7 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab // c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ // crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] // #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + // Pre-calculate (constant) column offsets, use columns 4..7 for big-endian. const int ix0 = 4*(4*CRC32_COLUMN_SIZE); const int ix1 = 5*(4*CRC32_COLUMN_SIZE); const int ix2 = 6*(4*CRC32_COLUMN_SIZE); @@ -5986,17 +6054,12 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab rotate_then_insert(t1, t0, 56-2, 63-2, 2-16, true); // ((c >> 16) & 0xff) << 2 rotate_then_insert(t0, t0, 56-2, 63-2, 2-24, true); // ((c >> 24) & 0xff) << 2 - // Load pre-calculated table values. - // Use columns 4..7 for big-endian. - z_ly(t3, Address(table, t3, (intptr_t)ix0)); + // XOR indexed table values to calculate updated crc. z_ly(t2, Address(table, t2, (intptr_t)ix1)); - z_ly(t1, Address(table, t1, (intptr_t)ix2)); z_ly(t0, Address(table, t0, (intptr_t)ix3)); - - // Calculate new crc from table values. - z_xr(t2, t3); - z_xr(t0, t1); - z_xr(t0, t2); // Now crc contains the final checksum value. + z_xy(t2, Address(table, t3, (intptr_t)ix0)); + z_xy(t0, Address(table, t1, (intptr_t)ix2)); + z_xr(t0, t2); // Now t0 contains the updated CRC value. lgr_if_needed(crc, t0); } @@ -6009,7 +6072,8 @@ void MacroAssembler::update_1word_crc32(Register crc, Register buf, Register tab * uses Z_R10..Z_R13 as work register. Must be saved/restored by caller! */ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3) { + Register t0, Register t1, Register t2, Register t3, + bool invertCRC) { assert_different_registers(crc, buf, len, table); Label L_mainLoop, L_tail; @@ -6024,7 +6088,9 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len // The situation itself is detected and handled correctly by the conditional branches // following aghi(len, -stepping) and aghi(len, +stepping). - not_(crc, noreg, false); // 1s complement of crc + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } #if 0 { @@ -6039,7 +6105,7 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len rotate_then_insert(ctr, ctr, 62, 63, 0, true); // TODO: should set cc z_sgfr(len, ctr); // Remaining len after alignment. - update_byteLoop_crc32(crc, buf, ctr, table, data, false); + update_byteLoop_crc32(crc, buf, ctr, table, data); } #endif @@ -6047,21 +6113,23 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len z_srag(ctr, len, log_stepping); z_brnh(L_tail); - z_lrvr(crc, crc); // Revert byte order because we are dealing with big-endian data. + z_lrvr(crc, crc); // Revert byte order because we are dealing with big-endian data. rotate_then_insert(len, len, 64-log_stepping, 63, 0, true); // #bytes for tailLoop BIND(L_mainLoop); update_1word_crc32(crc, buf, table, 0, 0, crc, t1, t2, t3); update_1word_crc32(crc, buf, table, 4, mainLoop_stepping, crc, t1, t2, t3); - z_brct(ctr, L_mainLoop); // Iterate. + z_brct(ctr, L_mainLoop); // Iterate. - z_lrvr(crc, crc); // Revert byte order back to original. + z_lrvr(crc, crc); // Revert byte order back to original. // Process last few (<8) bytes of buffer. BIND(L_tail); - update_byteLoop_crc32(crc, buf, len, table, data, false); + update_byteLoop_crc32(crc, buf, len, table, data); - not_(crc, noreg, false); // 1s complement of crc + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } } /** @@ -6073,7 +6141,8 @@ void MacroAssembler::kernel_crc32_2word(Register crc, Register buf, Register len * uses Z_R10..Z_R13 as work register. Must be saved/restored by caller! */ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3) { + Register t0, Register t1, Register t2, Register t3, + bool invertCRC) { assert_different_registers(crc, buf, len, table); Label L_mainLoop, L_tail; @@ -6087,7 +6156,9 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len // The situation itself is detected and handled correctly by the conditional branches // following aghi(len, -stepping) and aghi(len, +stepping). - not_(crc, noreg, false); // 1s complement of crc + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } // Check for short (<4 bytes) buffer. z_srag(ctr, len, log_stepping); @@ -6099,13 +6170,16 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len BIND(L_mainLoop); update_1word_crc32(crc, buf, table, 0, mainLoop_stepping, crc, t1, t2, t3); z_brct(ctr, L_mainLoop); // Iterate. + z_lrvr(crc, crc); // Revert byte order back to original. // Process last few (<8) bytes of buffer. BIND(L_tail); - update_byteLoop_crc32(crc, buf, len, table, data, false); + update_byteLoop_crc32(crc, buf, len, table, data); - not_(crc, noreg, false); // 1s complement of crc + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } } /** @@ -6115,22 +6189,51 @@ void MacroAssembler::kernel_crc32_1word(Register crc, Register buf, Register len * @param table register pointing to CRC table */ void MacroAssembler::kernel_crc32_1byte(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3) { + Register t0, Register t1, Register t2, Register t3, + bool invertCRC) { assert_different_registers(crc, buf, len, table); Register data = t0; - update_byteLoop_crc32(crc, buf, len, table, data, true); + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } + + update_byteLoop_crc32(crc, buf, len, table, data); + + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } } -void MacroAssembler::kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp) { +void MacroAssembler::kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp, + bool invertCRC) { assert_different_registers(crc, buf, len, table, tmp); - not_(crc, noreg, false); // ~c + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } z_llgc(tmp, Address(buf, (intptr_t)0)); // Current byte of input buffer (zero extended). Avoids garbage in upper half of register. update_byte_crc32(crc, tmp, table); - not_(crc, noreg, false); // ~c + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } +} + +void MacroAssembler::kernel_crc32_singleByteReg(Register crc, Register val, Register table, + bool invertCRC) { + assert_different_registers(crc, val, table); + + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } + + update_byte_crc32(crc, val, table); + + if (invertCRC) { + not_(crc, noreg, false); // 1s complement of crc + } } // @@ -6583,11 +6686,12 @@ void MacroAssembler::verify_oop(Register oop, const char* msg) { BLOCK_COMMENT("verify_oop {"); Register tmp = Z_R0; - unsigned int nbytes_save = 6 *8; + unsigned int nbytes_save = 5*BytesPerWord; address entry = StubRoutines::verify_oop_subroutine_entry_address(); + save_return_pc(); push_frame_abi160(nbytes_save); - z_stmg(Z_R0, Z_R5, 160, Z_SP); + z_stmg(Z_R1, Z_R5, frame::z_abi_160_size, Z_SP); z_lgr(Z_ARG2, oop); load_const(Z_ARG1, (address) msg); @@ -6595,10 +6699,10 @@ void MacroAssembler::verify_oop(Register oop, const char* msg) { z_lg(Z_R1, 0, Z_R1); call_c(Z_R1); - z_lmg(Z_R0, Z_R5, 160, Z_SP); + z_lmg(Z_R1, Z_R5, frame::z_abi_160_size, Z_SP); pop_frame(); - restore_return_pc(); + BLOCK_COMMENT("} verify_oop "); } @@ -6620,8 +6724,8 @@ void MacroAssembler::stop(int type, const char* msg, int id) { // Setup arguments. load_const(Z_ARG1, (void*) stop_types[type%stop_end]); load_const(Z_ARG2, (void*) msg); - get_PC(Z_R14); // Following code pushes a frame without entering a new function. Use current pc as return address. - save_return_pc(); // Saves return pc Z_R14. + get_PC(Z_R14); // Following code pushes a frame without entering a new function. Use current pc as return address. + save_return_pc(); // Saves return pc Z_R14. push_frame_abi160(0); call_VM_leaf(CAST_FROM_FN_PTR(address, stop_on_request), Z_ARG1, Z_ARG2); // The plain disassembler does not recognize illtrap. It instead displays diff --git a/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp b/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp index 2b4002a3bf4..8adc7544af5 100644 --- a/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp +++ b/hotspot/src/cpu/s390/vm/macroAssembler_s390.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. 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 @@ -440,9 +440,21 @@ class MacroAssembler: public Assembler { // Get current PC + offset. Offset given in bytes, must be even! address get_PC(Register result, int64_t offset); + // Accessing, and in particular modifying, a stack location is only safe if + // the stack pointer (Z_SP) is set such that the accessed stack location is + // in the reserved range. + // + // From a performance point of view, it is desirable not to change the SP + // first and then immediately use it to access the freshly reserved space. + // That opens a small gap, though. If, just after storing some value (the + // frame pointer) into the to-be-reserved space, an interrupt is caught, + // the handler might use the space beyond Z_SP for it's own purpose. + // If that happens, the stored value might get altered. + // Resize current frame either relatively wrt to current SP or absolute. void resize_frame_sub(Register offset, Register fp, bool load_fp=true); - void resize_frame_absolute(Register addr, Register fp, bool load_fp=true); + void resize_frame_abs_with_offset(Register newSP, Register fp, int offset, bool load_fp); + void resize_frame_absolute(Register addr, Register fp, bool load_fp); void resize_frame(RegisterOrConstant offset, Register fp, bool load_fp=true); // Push a frame of size bytes, if copy_sp is false, old_sp must already @@ -461,6 +473,8 @@ class MacroAssembler: public Assembler { // Pop current C frame. void pop_frame(); + // Pop current C frame and restore return PC register (Z_R14). + void pop_frame_restore_retPC(int frame_size_in_bytes); // // Calls @@ -1011,22 +1025,35 @@ class MacroAssembler: public Assembler { int before = 0, int after = 0) PRODUCT_RETURN; // Emitters for CRC32 calculation. + // A note on invertCRC: + // Unfortunately, internal representation of crc differs between CRC32 and CRC32C. + // CRC32 holds it's current crc value in the externally visible representation. + // CRC32C holds it's current crc value in internal format, ready for updating. + // Thus, the crc value must be bit-flipped before updating it in the CRC32 case. + // In the CRC32C case, it must be bit-flipped when it is given to the outside world (getValue()). + // The bool invertCRC parameter indicates whether bit-flipping is required before updates. private: void fold_byte_crc32(Register crc, Register table, Register val, Register tmp); void fold_8bit_crc32(Register crc, Register table, Register tmp); + void update_byte_crc32( Register crc, Register val, Register table); void update_byteLoop_crc32(Register crc, Register buf, Register len, Register table, - Register data, bool invertCRC); + Register data); void update_1word_crc32(Register crc, Register buf, Register table, int bufDisp, int bufInc, Register t0, Register t1, Register t2, Register t3); public: - void update_byte_crc32( Register crc, Register val, Register table); - void kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp); + void kernel_crc32_singleByteReg(Register crc, Register val, Register table, + bool invertCRC); + void kernel_crc32_singleByte(Register crc, Register buf, Register len, Register table, Register tmp, + bool invertCRC); void kernel_crc32_1byte(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3); + Register t0, Register t1, Register t2, Register t3, + bool invertCRC); void kernel_crc32_1word(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3); + Register t0, Register t1, Register t2, Register t3, + bool invertCRC); void kernel_crc32_2word(Register crc, Register buf, Register len, Register table, - Register t0, Register t1, Register t2, Register t3); + Register t0, Register t1, Register t2, Register t3, + bool invertCRC); // Emitters for BigInteger.multiplyToLen intrinsic // note: length of result array (zlen) is passed on the stack diff --git a/hotspot/src/cpu/s390/vm/metaspaceShared_s390.cpp b/hotspot/src/cpu/s390/vm/metaspaceShared_s390.cpp deleted file mode 100644 index 8e7feacf527..00000000000 --- a/hotspot/src/cpu/s390/vm/metaspaceShared_s390.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. 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 "asm/codeBuffer.hpp" -#include "asm/macroAssembler.inline.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->klass_part()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size();. -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no releationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#undef __ -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - __ unimplemented(); -} diff --git a/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp b/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp index e2f0d32cc8a..60577fd04a3 100644 --- a/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp +++ b/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. 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 @@ -29,6 +29,7 @@ #include "interpreter/interpreter.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" +#include "prims/jvm.h" #include "prims/methodHandles.hpp" #ifdef PRODUCT @@ -73,7 +74,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); assert(temp_reg != Z_R0 && // Is used as base register! temp_reg != noreg && temp2_reg != noreg, "need valid registers!"); @@ -200,10 +201,13 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()))); __ verify_oop(method_temp); - // The following assumes that a method is normally compressed in the vmtarget field. + __ load_heap_oop(method_temp, + Address(method_temp, + NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()))); + __ verify_oop(method_temp); __ z_lg(method_temp, Address(method_temp, - NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()))); + NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()))); if (VerifyMethodHandles && !for_compiler_entry) { // Make sure recv is already on stack. @@ -371,7 +375,8 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes())); Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes())); - Address member_vmtarget(member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())); + Address member_vmtarget(member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())); + Address vmtarget_method(Z_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())); Register temp1_recv_klass = temp1; if (iid != vmIntrinsics::_linkToStatic) { @@ -424,7 +429,8 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3); } - __ z_lg(Z_method, member_vmtarget); + __ load_heap_oop(Z_method, member_vmtarget); + __ z_lg(Z_method, vmtarget_method); method_is_live = true; break; @@ -432,7 +438,8 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3); } - __ z_lg(Z_method, member_vmtarget); + __ load_heap_oop(Z_method, member_vmtarget); + __ z_lg(Z_method, vmtarget_method); method_is_live = true; break; @@ -602,14 +609,14 @@ void trace_method_handle_stub(const char* adaptername, void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adaptername) { if (!TraceMethodHandles) { return; } + // If arg registers are contiguous, we can use STMG/LMG. + assert((Z_ARG5->encoding() - Z_ARG1->encoding() + 1) == RegisterImpl::number_of_arg_registers, "Oops"); + BLOCK_COMMENT("trace_method_handle {"); // Save argument registers (they are used in raise exception stub). - __ z_stg(Z_ARG1, Address(Z_SP, 16)); - __ z_stg(Z_ARG2, Address(Z_SP, 24)); - __ z_stg(Z_ARG3, Address(Z_SP, 32)); - __ z_stg(Z_ARG4, Address(Z_SP, 40)); - __ z_stg(Z_ARG5, Address(Z_SP, 48)); + // Argument registers have contiguous register numbers -> we can use stmg/lmg. + __ z_stmg(Z_ARG1, Z_ARG5, 16, Z_SP); // Setup arguments. __ z_lgr(Z_ARG2, Z_ARG4); // mh, see generate_method_handle_interpreter_entry() @@ -622,11 +629,9 @@ void MethodHandles::trace_method_handle(MacroAssembler* _masm, const char* adapt __ call_VM_leaf(CAST_FROM_FN_PTR(address, trace_method_handle_stub)); __ pop_frame(); __ restore_return_pc(); // restores to Z_R14 - __ z_lg(Z_ARG1, Address(Z_SP, 16)); - __ z_lg(Z_ARG2, Address(Z_SP, 24)); - __ z_lg(Z_ARG3, Address(Z_SP, 32)); - __ z_lg(Z_ARG4, Address(Z_SP, 40)); - __ z_lg(Z_ARG5, Address(Z_SP, 45)); + + // Restore argument registers + __ z_lmg(Z_ARG1, Z_ARG5, 16, Z_SP); __ zap_from_to(Z_SP, Z_SP, Z_R0, Z_R1, 50, -1); __ zap_from_to(Z_SP, Z_SP, Z_R0, Z_R1, -1, 5); diff --git a/hotspot/src/cpu/s390/vm/s390.ad b/hotspot/src/cpu/s390/vm/s390.ad index 7daf348c0af..b30437e0faf 100644 --- a/hotspot/src/cpu/s390/vm/s390.ad +++ b/hotspot/src/cpu/s390/vm/s390.ad @@ -1,6 +1,6 @@ // -// Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. -// Copyright (c) 2016 SAP SE. All rights reserved. +// Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2017, SAP SE. 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 @@ -910,16 +910,8 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { bool need_polling = do_polling() && C->is_method_compilation(); // Pop frame, restore return_pc, and all stuff needed by interpreter. - // Pop frame by add instead of load (a penny saved is a penny got :-). int frame_size_in_bytes = Assembler::align((C->frame_slots() << LogBytesPerInt), frame::alignment_in_bytes); - int retPC_offset = frame_size_in_bytes + _z_abi16(return_pc); - if (Displacement::is_validDisp(retPC_offset)) { - __ z_lg(Z_R14, retPC_offset, Z_SP); - __ add2reg(Z_SP, frame_size_in_bytes); - } else { - __ add2reg(Z_SP, frame_size_in_bytes); - __ restore_return_pc(); - } + __ pop_frame_restore_retPC(frame_size_in_bytes); if (StackReservedPages > 0 && C->has_reserved_stack_access()) { __ reserved_stack_check(Z_R14); @@ -1562,7 +1554,7 @@ const int Matcher::vector_width_in_bytes(BasicType bt) { } // Vector ideal reg. -const int Matcher::vector_ideal_reg(int size) { +const uint Matcher::vector_ideal_reg(int size) { assert(MaxVectorSize == 8 && size == 8, ""); return Op_RegL; } @@ -1577,7 +1569,7 @@ const int Matcher::min_vector_size(const BasicType bt) { return max_vector_size(bt); // Same as max. } -const int Matcher::vector_shift_count_ideal_reg(int size) { +const uint Matcher::vector_shift_count_ideal_reg(int size) { fatal("vector shift is not supported"); return Node::NotAMachineReg; } @@ -6768,6 +6760,7 @@ instruct sllI_reg_imm(iRegI dst, iRegI src, immI nbits) %{ format %{ "SLL $dst,$src,$nbits\t# use RISC-like SLLG also for int" %} ins_encode %{ int Nbit = $nbits$$constant; + assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph"); __ z_sllg($dst$$Register, $src$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); %} ins_pipe(pipe_class_dummy); @@ -6841,6 +6834,7 @@ instruct sraI_reg_imm(iRegI dst, immI src, flagsReg cr) %{ format %{ "SRA $dst,$src" %} ins_encode %{ int Nbit = $src$$constant; + assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph"); __ z_sra($dst$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); %} ins_pipe(pipe_class_dummy); @@ -6893,6 +6887,7 @@ instruct srlI_reg_imm(iRegI dst, immI src) %{ format %{ "SRL $dst,$src" %} ins_encode %{ int Nbit = $src$$constant; + assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph"); __ z_srl($dst$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); %} ins_pipe(pipe_class_dummy); diff --git a/hotspot/src/cpu/s390/vm/sharedRuntime_s390.cpp b/hotspot/src/cpu/s390/vm/sharedRuntime_s390.cpp index 89c3ae4032a..d8c1a63728b 100644 --- a/hotspot/src/cpu/s390/vm/sharedRuntime_s390.cpp +++ b/hotspot/src/cpu/s390/vm/sharedRuntime_s390.cpp @@ -35,6 +35,7 @@ #include "registerSaver_s390.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/align.hpp" #include "vmreg_s390.inline.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" @@ -311,7 +312,13 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, RegisterSet reg __ save_return_pc(return_pc); // Push a new frame (includes stack linkage). - __ push_frame(frame_size_in_bytes); + // use return_pc as scratch for push_frame. Z_R0_scratch (the default) and Z_R1_scratch are + // illegally used to pass parameters (SAPJVM extension) by RangeCheckStub::emit_code(). + __ push_frame(frame_size_in_bytes, return_pc); + // We have to restore return_pc right away. + // Nobody else will. Furthermore, return_pc isn't necessarily the default (Z_R14). + // Nobody else knows which register we saved. + __ z_lg(return_pc, _z_abi16(return_pc) + frame_size_in_bytes, Z_SP); // Register save area in new frame starts above z_abi_160 area. int offset = register_save_offset; @@ -541,7 +548,6 @@ void RegisterSaver::restore_result_registers(MacroAssembler* masm) { } } -#if INCLUDE_CDS size_t SharedRuntime::trampoline_size() { return MacroAssembler::load_const_size() + 2; } @@ -551,7 +557,6 @@ void SharedRuntime::generate_trampoline(MacroAssembler *masm, address destinatio __ load_const(Z_R1_scratch, destination); __ z_br(Z_R1_scratch); } -#endif // --------------------------------------------------------------------------- void SharedRuntime::save_native_result(MacroAssembler * masm, @@ -744,7 +749,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt, ShouldNotReachHere(); } } - return round_to(stk, 2); + return align_up(stk, 2); } int SharedRuntime::c_calling_convention(const BasicType *sig_bt, @@ -840,7 +845,7 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt, ShouldNotReachHere(); } } - return round_to(stk, 2); + return align_up(stk, 2); } //////////////////////////////////////////////////////////////////////// @@ -1734,7 +1739,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, } } } // for - total_save_slots = double_slots * 2 + round_to(single_slots, 2); // Round to even. + total_save_slots = double_slots * 2 + align_up(single_slots, 2); // Round to even. } int oop_handle_slot_offset = stack_slots; @@ -1761,7 +1766,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm, // Now compute actual number of stack words we need. // Round to align stack properly. - stack_slots = round_to(stack_slots, // 7) + stack_slots = align_up(stack_slots, // 7) frame::alignment_in_bytes / VMRegImpl::stack_slot_size); int frame_size_in_bytes = stack_slots * VMRegImpl::stack_slot_size; @@ -2395,7 +2400,7 @@ static address gen_c2i_adapter(MacroAssembler *masm, // it has already been allocated. const int abi_scratch = frame::z_top_ijava_frame_abi_size; - int extraspace = round_to(total_args_passed, 2)*wordSize + abi_scratch; + int extraspace = align_up(total_args_passed, 2)*wordSize + abi_scratch; Register sender_SP = Z_R10; Register value = Z_R12; @@ -2525,9 +2530,9 @@ void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm, // registers are below. By subtracting stack0, we either get a negative // number (all values in registers) or the maximum stack slot accessed. // Convert VMRegImpl (4 byte) stack slots to words. - int comp_words_on_stack = round_to(comp_args_on_stack*VMRegImpl::stack_slot_size, wordSize)>>LogBytesPerWord; + int comp_words_on_stack = align_up(comp_args_on_stack*VMRegImpl::stack_slot_size, wordSize)>>LogBytesPerWord; // Round up to miminum stack alignment, in wordSize - comp_words_on_stack = round_to(comp_words_on_stack, 2); + comp_words_on_stack = align_up(comp_words_on_stack, 2); __ resize_frame(-comp_words_on_stack*wordSize, Z_R0_scratch); } diff --git a/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp b/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp index be107222636..d779e90c042 100644 --- a/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp +++ b/hotspot/src/cpu/s390/vm/stubGenerator_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. 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 @@ -291,7 +291,7 @@ class StubGenerator: public StubCodeGenerator { // Restore frame pointer. __ z_lg(r_entryframe_fp, _z_abi(callers_sp), Z_SP); // Pop frame. Done here to minimize stalls. - __ z_lg(Z_SP, _z_abi(callers_sp), Z_SP); + __ pop_frame(); // Reload some volatile registers which we've spilled before the call // to frame manager / native entry. @@ -563,6 +563,9 @@ class StubGenerator: public StubCodeGenerator { address generate_throw_exception(const char* name, address runtime_entry, bool restore_saved_exception_pc, Register arg1 = noreg, Register arg2 = noreg) { + assert_different_registers(arg1, Z_R0_scratch); // would be destroyed by push_frame() + assert_different_registers(arg2, Z_R0_scratch); // would be destroyed by push_frame() + int insts_size = 256; int locs_size = 0; CodeBuffer code(name, insts_size, locs_size); @@ -623,26 +626,6 @@ class StubGenerator: public StubCodeGenerator { #define __ (Verbose ? (_masm->block_comment(FILE_AND_LINE),_masm):_masm)-> #endif - //---------------------------------------------------------------------- - // The following routine generates a subroutine to throw an asynchronous - // UnknownError when an unsafe access gets a fault that could not be - // reasonably prevented by the programmer. (Example: SIGBUS/OBJERR.) - // - // Arguments: - // trapping PC: ?? - // - // Results: - // Posts an asynchronous exception, skips the trapping instruction. - // - address generate_handler_for_unsafe_access() { - StubCodeMark mark(this, "StubRoutines", "handler_for_unsafe_access"); - { - address start = __ pc(); - __ unimplemented("StubRoutines::handler_for_unsafe_access", 86); - return start; - } - } - // Support for uint StubRoutine::zarch::partial_subtype_check(Klass // sub, Klass super); // @@ -713,11 +696,13 @@ class StubGenerator: public StubCodeGenerator { BarrierSet* const bs = Universe::heap()->barrier_set(); switch (bs->kind()) { case BarrierSet::G1SATBCTLogging: - // With G1, don't generate the call if we statically know that the target in uninitialized. + // With G1, don't generate the call if we statically know that the target is uninitialized. if (!dest_uninitialized) { // Is marking active? Label filtered; - Register Rtmp1 = Z_R0; + assert_different_registers(addr, Z_R0_scratch); // would be destroyed by push_frame() + assert_different_registers(count, Z_R0_scratch); // would be destroyed by push_frame() + Register Rtmp1 = Z_R0_scratch; const int active_offset = in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()); if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) { @@ -728,11 +713,11 @@ class StubGenerator: public StubCodeGenerator { } __ z_bre(filtered); // Activity indicator is zero, so there is no marking going on currently. - // __ push_frame_abi160(0); + // __ push_frame_abi160(0); // implicitly done in save_live_registers() (void) RegisterSaver::save_live_registers(_masm, RegisterSaver::arg_registers); __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), addr, count); (void) RegisterSaver::restore_live_registers(_masm, RegisterSaver::arg_registers); - // __ pop_frame(); + // __ pop_frame(); // implicitly done in restore_live_registers() __ bind(filtered); } @@ -759,16 +744,18 @@ class StubGenerator: public StubCodeGenerator { case BarrierSet::G1SATBCTLogging: { if (branchToEnd) { - // __ push_frame_abi160(0); + assert_different_registers(addr, Z_R0_scratch); // would be destroyed by push_frame() + assert_different_registers(count, Z_R0_scratch); // would be destroyed by push_frame() + // __ push_frame_abi160(0); // implicitly done in save_live_registers() (void) RegisterSaver::save_live_registers(_masm, RegisterSaver::arg_registers); __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post), addr, count); (void) RegisterSaver::restore_live_registers(_masm, RegisterSaver::arg_registers); - // __ pop_frame(); + // __ pop_frame(); // implicitly done in restore_live_registers() } else { // Tail call: call c and return to stub caller. address entry_point = CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_post); - if (Z_ARG1 != addr) __ z_lgr(Z_ARG1, addr); - if (Z_ARG2 != count) __ z_lgr(Z_ARG2, count); + __ lgr_if_needed(Z_ARG1, addr); + __ lgr_if_needed(Z_ARG2, count); __ load_const(Z_R1, entry_point); __ z_br(Z_R1); // Branch without linking, callee will return to stub caller. } @@ -1696,8 +1683,8 @@ class StubGenerator: public StubCodeGenerator { // src must designate an even/odd register pair, holding the address/length of the original message // Helper function which generates code to - // - load the function code in register fCode (== Z_R0) - // - load the data block length (depends on cipher function) in register srclen if requested. + // - load the function code in register fCode (== Z_R0). + // - load the data block length (depends on cipher function) into register srclen if requested. // - is_decipher switches between cipher/decipher function codes // - set_len requests (if true) loading the data block length in register srclen void generate_load_AES_fCode(Register keylen, Register fCode, Register srclen, bool is_decipher) { @@ -1708,12 +1695,13 @@ class StubGenerator: public StubCodeGenerator { bool identical_dataBlk_len = (VM_Version::Cipher::_AES128_dataBlk == VM_Version::Cipher::_AES192_dataBlk) && (VM_Version::Cipher::_AES128_dataBlk == VM_Version::Cipher::_AES256_dataBlk); // Expanded key length is 44/52/60 * 4 bytes for AES-128/AES-192/AES-256. - __ z_cghi(keylen, 52); - __ z_lghi(fCode, VM_Version::Cipher::_AES256 + mode); + __ z_cghi(keylen, 52); // Check only once at the beginning. keylen and fCode may share the same register. + + __ z_lghi(fCode, VM_Version::Cipher::_AES128 + mode); if (!identical_dataBlk_len) { - __ z_lghi(srclen, VM_Version::Cipher::_AES256_dataBlk); + __ z_lghi(srclen, VM_Version::Cipher::_AES128_dataBlk); } - __ z_brh(fCode_set); // keyLen > 52: AES256 + __ z_brl(fCode_set); // keyLen < 52: AES128 __ z_lghi(fCode, VM_Version::Cipher::_AES192 + mode); if (!identical_dataBlk_len) { @@ -1721,11 +1709,12 @@ class StubGenerator: public StubCodeGenerator { } __ z_bre(fCode_set); // keyLen == 52: AES192 - __ z_lghi(fCode, VM_Version::Cipher::_AES128 + mode); + __ z_lghi(fCode, VM_Version::Cipher::_AES256 + mode); if (!identical_dataBlk_len) { - __ z_lghi(srclen, VM_Version::Cipher::_AES128_dataBlk); + __ z_lghi(srclen, VM_Version::Cipher::_AES256_dataBlk); } - // __ z_brl(fCode_set); // keyLen < 52: AES128 // fallthru + // __ z_brh(fCode_set); // keyLen < 52: AES128 // fallthru + __ bind(fCode_set); if (identical_dataBlk_len) { __ z_lghi(srclen, VM_Version::Cipher::_AES128_dataBlk); @@ -1735,6 +1724,54 @@ class StubGenerator: public StubCodeGenerator { } // Push a parameter block for the cipher/decipher instruction on the stack. + // Layout of the additional stack space allocated for AES_cipherBlockChaining: + // + // | | + // +--------+ <-- SP before expansion + // | | + // : : alignment loss, 0..(AES_parmBlk_align-8) bytes + // | | + // +--------+ + // | | + // : : space for parameter block, size VM_Version::Cipher::_AES*_parmBlk_C + // | | + // +--------+ <-- parmBlk, octoword-aligned, start of parameter block + // | | + // : : additional stack space for spills etc., size AES_parmBlk_addspace, DW @ Z_SP not usable!!! + // | | + // +--------+ <-- Z_SP after expansion + + void generate_push_Block(int dataBlk_len, int parmBlk_len, int crypto_fCode, + Register parmBlk, Register keylen, Register fCode, Register cv, Register key) { + const int AES_parmBlk_align = 32; // octoword alignment. + const int AES_parmBlk_addspace = 24; // Must be sufficiently large to hold all spilled registers + // (currently 2) PLUS 1 DW for the frame pointer. + + const int cv_len = dataBlk_len; + const int key_len = parmBlk_len - cv_len; + // This len must be known at JIT compile time. Only then are we able to recalc the SP before resize. + // We buy this knowledge by wasting some (up to AES_parmBlk_align) bytes of stack space. + const int resize_len = cv_len + key_len + AES_parmBlk_align + AES_parmBlk_addspace; + + // Use parmBlk as temp reg here to hold the frame pointer. + __ resize_frame(-resize_len, parmBlk, true); + + // calculate parmBlk address from updated (resized) SP. + __ add2reg(parmBlk, resize_len - (cv_len + key_len), Z_SP); + __ z_nill(parmBlk, (~(AES_parmBlk_align-1)) & 0xffff); // Align parameter block. + + // There is room for stuff in the range [parmBlk-AES_parmBlk_addspace+8, parmBlk). + __ z_stg(keylen, -8, parmBlk); // Spill keylen for later use. + + // calculate (SP before resize) from updated SP. + __ add2reg(keylen, resize_len, Z_SP); // keylen holds prev SP for now. + __ z_stg(keylen, -16, parmBlk); // Spill prev SP for easy revert. + + __ z_mvc(0, cv_len-1, parmBlk, 0, cv); // Copy cv. + __ z_mvc(cv_len, key_len-1, parmBlk, 0, key); // Copy key. + __ z_lghi(fCode, crypto_fCode); + } + // NOTE: // Before returning, the stub has to copy the chaining value from // the parmBlk, where it was updated by the crypto instruction, back @@ -1743,17 +1780,14 @@ class StubGenerator: public StubCodeGenerator { // the key length across the KMC instruction. We do so by spilling it to the stack, // just preceding the parmBlk (at (parmBlk - 8)). void generate_push_parmBlk(Register keylen, Register fCode, Register parmBlk, Register key, Register cv, bool is_decipher) { - const int AES_parmBlk_align = 32; - const int AES_parmBlk_addspace = AES_parmBlk_align; // Must be multiple of AES_parmblk_align. - int cv_len, key_len; int mode = is_decipher ? VM_Version::CipherMode::decipher : VM_Version::CipherMode::cipher; Label parmBlk_128, parmBlk_192, parmBlk_256, parmBlk_set; BLOCK_COMMENT("push parmBlk {"); if (VM_Version::has_Crypto_AES() ) { __ z_cghi(keylen, 52); } - if (VM_Version::has_Crypto_AES256()) { __ z_brh(parmBlk_256); } // keyLen > 52: AES256 - if (VM_Version::has_Crypto_AES192()) { __ z_bre(parmBlk_192); } // keyLen == 52: AES192 if (VM_Version::has_Crypto_AES128()) { __ z_brl(parmBlk_128); } // keyLen < 52: AES128 + if (VM_Version::has_Crypto_AES192()) { __ z_bre(parmBlk_192); } // keyLen == 52: AES192 + if (VM_Version::has_Crypto_AES256()) { __ z_brh(parmBlk_256); } // keyLen > 52: AES256 // Security net: requested AES function not available on this CPU. // NOTE: @@ -1762,71 +1796,35 @@ class StubGenerator: public StubCodeGenerator { // at all, we have at least AES-128. __ stop_static("AES key strength not supported by CPU. Use -XX:-UseAES as remedy.", 0); - if (VM_Version::has_Crypto_AES128()) { - __ bind(parmBlk_128); - cv_len = VM_Version::Cipher::_AES128_dataBlk; - key_len = VM_Version::Cipher::_AES128_parmBlk_C - cv_len; - __ z_lay(parmBlk, -(VM_Version::Cipher::_AES128_parmBlk_C+AES_parmBlk_align)+(AES_parmBlk_align-1), Z_SP); - __ z_nill(parmBlk, (~(AES_parmBlk_align-1)) & 0xffff); // align parameter block - - // Resize the frame to accommodate for the aligned parameter block and other stuff. - // There is room for stuff in the range [parmBlk-AES_parmBlk_addspace, parmBlk). - __ z_stg(keylen, -8, parmBlk); // Spill keylen for later use. - __ z_stg(Z_SP, -16, parmBlk); // Spill SP for easy revert. - __ z_aghi(parmBlk, -AES_parmBlk_addspace); // Additional space for keylen, etc.. - __ resize_frame_absolute(parmBlk, keylen, true); // Resize frame with parmBlk being the new SP. - __ z_aghi(parmBlk, AES_parmBlk_addspace); // Restore parameter block address. - - __ z_mvc(0, cv_len-1, parmBlk, 0, cv); // Copy cv. - __ z_mvc(cv_len, key_len-1, parmBlk, 0, key); // Copy key. - __ z_lghi(fCode, VM_Version::Cipher::_AES128 + mode); - if (VM_Version::has_Crypto_AES192() || VM_Version::has_Crypto_AES256()) { + if (VM_Version::has_Crypto_AES256()) { + __ bind(parmBlk_256); + generate_push_Block(VM_Version::Cipher::_AES256_dataBlk, + VM_Version::Cipher::_AES256_parmBlk_C, + VM_Version::Cipher::_AES256 + mode, + parmBlk, keylen, fCode, cv, key); + if (VM_Version::has_Crypto_AES128() || VM_Version::has_Crypto_AES192()) { __ z_bru(parmBlk_set); // Fallthru otherwise. } } if (VM_Version::has_Crypto_AES192()) { __ bind(parmBlk_192); - cv_len = VM_Version::Cipher::_AES192_dataBlk; - key_len = VM_Version::Cipher::_AES192_parmBlk_C - cv_len; - __ z_lay(parmBlk, -(VM_Version::Cipher::_AES192_parmBlk_C+AES_parmBlk_align)+(AES_parmBlk_align-1), Z_SP); - __ z_nill(parmBlk, (~(AES_parmBlk_align-1)) & 0xffff); // Align parameter block. - - // Resize the frame to accommodate for the aligned parameter block and other stuff. - // There is room for stuff in the range [parmBlk-AES_parmBlk_addspace, parmBlk). - __ z_stg(keylen, -8, parmBlk); // Spill keylen for later use. - __ z_stg(Z_SP, -16, parmBlk); // Spill SP for easy revert. - __ z_aghi(parmBlk, -AES_parmBlk_addspace); // Additional space for keylen, etc.. - __ resize_frame_absolute(parmBlk, keylen, true); // Resize frame with parmBlk being the new SP. - __ z_aghi(parmBlk, AES_parmBlk_addspace); // Restore parameter block address. - - __ z_mvc(0, cv_len-1, parmBlk, 0, cv); // Copy cv. - __ z_mvc(cv_len, key_len-1, parmBlk, 0, key); // Copy key. - __ z_lghi(fCode, VM_Version::Cipher::_AES192 + mode); - if (VM_Version::has_Crypto_AES256()) { + generate_push_Block(VM_Version::Cipher::_AES192_dataBlk, + VM_Version::Cipher::_AES192_parmBlk_C, + VM_Version::Cipher::_AES192 + mode, + parmBlk, keylen, fCode, cv, key); + if (VM_Version::has_Crypto_AES128()) { __ z_bru(parmBlk_set); // Fallthru otherwise. } } - if (VM_Version::has_Crypto_AES256()) { - __ bind(parmBlk_256); - cv_len = VM_Version::Cipher::_AES256_dataBlk; - key_len = VM_Version::Cipher::_AES256_parmBlk_C - cv_len; - __ z_lay(parmBlk, -(VM_Version::Cipher::_AES256_parmBlk_C+AES_parmBlk_align)+(AES_parmBlk_align-1), Z_SP); - __ z_nill(parmBlk, (~(AES_parmBlk_align-1)) & 0xffff); // Align parameter block. - - // Resize the frame to accommodate for the aligned parameter block and other stuff. - // There is room for stuff in the range [parmBlk-AES_parmBlk_addspace, parmBlk). - __ z_stg(keylen, -8, parmBlk); // Spill keylen for later use. - __ z_stg(Z_SP, -16, parmBlk); // Spill SP for easy revert. - __ z_aghi(parmBlk, -AES_parmBlk_addspace); // Additional space for keylen, etc.. - __ resize_frame_absolute(parmBlk, keylen, true); // Resize frame with parmBlk being the new SP. - __ z_aghi(parmBlk, AES_parmBlk_addspace); // Restore parameter block address. - - __ z_mvc(0, cv_len-1, parmBlk, 0, cv); // Copy cv. - __ z_mvc(cv_len, key_len-1, parmBlk, 0, key); // Copy key. - __ z_lghi(fCode, VM_Version::Cipher::_AES256 + mode); - // __ z_bru(parmBlk_set); // fallthru + if (VM_Version::has_Crypto_AES128()) { + __ bind(parmBlk_128); + generate_push_Block(VM_Version::Cipher::_AES128_dataBlk, + VM_Version::Cipher::_AES128_parmBlk_C, + VM_Version::Cipher::_AES128 + mode, + parmBlk, keylen, fCode, cv, key); + // Fallthru } __ bind(parmBlk_set); @@ -1882,41 +1880,49 @@ class StubGenerator: public StubCodeGenerator { } __ bind(parmBlk_set); } - __ z_lg(Z_SP, -16, parmBlk); // Revert resize_frame_absolute. + __ z_lg(Z_SP, -16, parmBlk); // Revert resize_frame_absolute. Z_SP saved by push_parmBlk. BLOCK_COMMENT("} pop parmBlk"); } - // Compute AES encrypt function. - address generate_AES_encryptBlock(const char* name) { - __ align(CodeEntryAlignment); - StubCodeMark mark(this, "StubRoutines", name); - unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). - + // Compute AES encrypt/decrypt function. + void generate_AES_cipherBlock(bool is_decipher) { + // Incoming arguments. Register from = Z_ARG1; // source byte array Register to = Z_ARG2; // destination byte array Register key = Z_ARG3; // expanded key array const Register keylen = Z_R0; // Temporarily (until fCode is set) holds the expanded key array length. + + // Register definitions as required by KM instruction. const Register fCode = Z_R0; // crypto function code const Register parmBlk = Z_R1; // parameter block address (points to crypto key) - const Register src = Z_ARG1; // is Z_R2 - const Register srclen = Z_ARG2; // Overwrites destination address. - const Register dst = Z_ARG3; // Overwrites expanded key address. + const Register src = Z_ARG1; // Must be even reg (KM requirement). + const Register srclen = Z_ARG2; // Must be odd reg and pair with src. Overwrites destination address. + const Register dst = Z_ARG3; // Must be even reg (KM requirement). Overwrites expanded key address. // Read key len of expanded key (in 4-byte words). __ z_lgf(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT))); // Copy arguments to registers as required by crypto instruction. __ z_lgr(parmBlk, key); // crypto key (in T_INT array). - // __ z_lgr(src, from); // Copy not needed, src/from are identical. - __ z_lgr(dst, to); // Copy destination address to even register. + __ lgr_if_needed(src, from); // Copy src address. Will not emit, src/from are identical. + __ z_lgr(dst, to); // Copy dst address, even register required. - // Construct function code in Z_R0, data block length in Z_ARG2. - generate_load_AES_fCode(keylen, fCode, srclen, false); + // Construct function code into fCode(Z_R0), data block length into srclen(Z_ARG2). + generate_load_AES_fCode(keylen, fCode, srclen, is_decipher); - __ km(dst, src); // Cipher the message. + __ km(dst, src); // Cipher the message. __ z_br(Z_R14); + } + + // Compute AES encrypt function. + address generate_AES_encryptBlock(const char* name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). + + generate_AES_cipherBlock(false); return __ addr_at(start_off); } @@ -1925,33 +1931,9 @@ class StubGenerator: public StubCodeGenerator { address generate_AES_decryptBlock(const char* name) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", name); - unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). + unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). - Register from = Z_ARG1; // source byte array - Register to = Z_ARG2; // destination byte array - Register key = Z_ARG3; // expanded key array, not preset at entry!!! - - const Register keylen = Z_R0; // Temporarily (until fCode is set) holds the expanded key array length. - const Register fCode = Z_R0; // crypto function code - const Register parmBlk = Z_R1; // parameter block address (points to crypto key) - const Register src = Z_ARG1; // is Z_R2 - const Register srclen = Z_ARG2; // Overwrites destination address. - const Register dst = Z_ARG3; // Overwrites key address. - - // Read key len of expanded key (in 4-byte words). - __ z_lgf(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT))); - - // Copy arguments to registers as required by crypto instruction. - __ z_lgr(parmBlk, key); // Copy crypto key address. - // __ z_lgr(src, from); // Copy not needed, src/from are identical. - __ z_lgr(dst, to); // Copy destination address to even register. - - // Construct function code in Z_R0, data block length in Z_ARG2. - generate_load_AES_fCode(keylen, fCode, srclen, true); - - __ km(dst, src); // Cipher the message. - - __ z_br(Z_R14); + generate_AES_cipherBlock(true); return __ addr_at(start_off); } @@ -1969,10 +1951,7 @@ class StubGenerator: public StubCodeGenerator { // We align the parameter block to the next available octoword. // // Compute chained AES encrypt function. - address generate_cipherBlockChaining_AES_encrypt(const char* name) { - __ align(CodeEntryAlignment); - StubCodeMark mark(this, "StubRoutines", name); - unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). + void generate_AES_cipherBlockChaining(bool is_decipher) { Register from = Z_ARG1; // source byte array (clear text) Register to = Z_ARG2; // destination byte array (ciphered) @@ -1992,20 +1971,29 @@ class StubGenerator: public StubCodeGenerator { __ z_lgf(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT))); // Construct parm block address in parmBlk (== Z_R1), copy cv and key to parm block. - // Construct function code in Z_R0. - generate_push_parmBlk(keylen, fCode, parmBlk, key, cv, false); + // Construct function code in fCode (Z_R0). + generate_push_parmBlk(keylen, fCode, parmBlk, key, cv, is_decipher); // Prepare other registers for instruction. - // __ z_lgr(src, from); // Not needed, registers are the same. + __ lgr_if_needed(src, from); // Copy src address. Will not emit, src/from are identical. __ z_lgr(dst, to); - __ z_llgfr(srclen, msglen); // We pass the offsets as ints, not as longs as required. + __ z_llgfr(srclen, msglen); // We pass the offsets as ints, not as longs as required. - __ kmc(dst, src); // Cipher the message. + __ kmc(dst, src); // Cipher the message. generate_pop_parmBlk(keylen, parmBlk, key, cv); - __ z_llgfr(Z_RET, msglen); // We pass the offsets as ints, not as longs as required. + __ z_llgfr(Z_RET, msglen); // We pass the offsets as ints, not as longs as required. __ z_br(Z_R14); + } + + // Compute chained AES encrypt function. + address generate_cipherBlockChaining_AES_encrypt(const char* name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). + + generate_AES_cipherBlockChaining(false); return __ addr_at(start_off); } @@ -2016,38 +2004,7 @@ class StubGenerator: public StubCodeGenerator { StubCodeMark mark(this, "StubRoutines", name); unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). - Register from = Z_ARG1; // source byte array (ciphered) - Register to = Z_ARG2; // destination byte array (clear text) - Register key = Z_ARG3; // expanded key array, not preset at entry!!! - Register cv = Z_ARG4; // chaining value - const Register msglen = Z_ARG5; // Total length of the msg to be encrypted. Value must be returned - // in Z_RET upon completion of this stub. - - const Register keylen = Z_R0; // Expanded key length, as read from key array. Temp only. - const Register fCode = Z_R0; // crypto function code - const Register parmBlk = Z_R1; // parameter block address (points to crypto key) - const Register src = Z_ARG1; // is Z_R2 - const Register srclen = Z_ARG2; // Overwrites destination address. - const Register dst = Z_ARG3; // Overwrites key address. - - // Read key len of expanded key (in 4-byte words). - __ z_lgf(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT))); - - // Construct parm block address in parmBlk (== Z_R1), copy cv and key to parm block. - // Construct function code in Z_R0. - generate_push_parmBlk(keylen, fCode, parmBlk, key, cv, true); - - // Prepare other registers for instruction. - // __ z_lgr(src, from); // Not needed, registers are the same. - __ z_lgr(dst, to); - __ z_llgfr(srclen, msglen); // We pass the offsets as ints, not as longs as required. - - __ kmc(dst, src); // Decipher the message. - - generate_pop_parmBlk(keylen, parmBlk, key, cv); - - __ z_llgfr(Z_RET, msglen); // We pass the offsets as ints, not as longs as required. - __ z_br(Z_R14); + generate_AES_cipherBlockChaining(true); return __ addr_at(start_off); } @@ -2330,26 +2287,25 @@ class StubGenerator: public StubCodeGenerator { } - - // Arguments: - // Z_ARG1 - int crc - // Z_ARG2 - byte* buf - // Z_ARG3 - int length (of buffer) - // - // Result: - // Z_RET - int crc result - // - // Compute CRC32 function. - address generate_CRC32_updateBytes(const char* name) { - __ align(CodeEntryAlignment); - StubCodeMark mark(this, "StubRoutines", name); - unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). + /** + * Arguments: + * + * Inputs: + * Z_ARG1 - int crc + * Z_ARG2 - byte* buf + * Z_ARG3 - int length (of buffer) + * + * Result: + * Z_RET - int crc result + **/ + // Compute CRC function (generic, for all polynomials). + void generate_CRC_updateBytes(const char* name, Register table, bool invertCRC) { // arguments to kernel_crc32: Register crc = Z_ARG1; // Current checksum, preset by caller or result from previous call, int. Register data = Z_ARG2; // source byte array Register dataLen = Z_ARG3; // #bytes to process, int - Register table = Z_ARG4; // crc table address +// Register table = Z_ARG4; // crc table address. Preloaded and passed in by caller. const Register t0 = Z_R10; // work reg for kernel* emitters const Register t1 = Z_R11; // work reg for kernel* emitters const Register t2 = Z_R12; // work reg for kernel* emitters @@ -2361,16 +2317,50 @@ class StubGenerator: public StubCodeGenerator { // Crc used as int. __ z_llgfr(dataLen, dataLen); - StubRoutines::zarch::generate_load_crc_table_addr(_masm, table); - __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. __ z_stmg(Z_R10, Z_R13, 1*8, Z_SP); // Spill regs 10..11 to make them available as work registers. - __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3); + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, invertCRC); __ z_lmg(Z_R10, Z_R13, 1*8, Z_SP); // Spill regs 10..11 back from stack. __ resize_frame(+(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. __ z_llgfr(Z_RET, crc); // Updated crc is function result. No copying required, just zero upper 32 bits. __ z_br(Z_R14); // Result already in Z_RET == Z_ARG1. + } + + + // Compute CRC32 function. + address generate_CRC32_updateBytes(const char* name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). + + assert(UseCRC32Intrinsics, "should not generate this stub (%s) with CRC32 intrinsics disabled", name); + + BLOCK_COMMENT("CRC32_updateBytes {"); + Register table = Z_ARG4; // crc32 table address. + StubRoutines::zarch::generate_load_crc_table_addr(_masm, table); + + generate_CRC_updateBytes(name, table, true); + BLOCK_COMMENT("} CRC32_updateBytes"); + + return __ addr_at(start_off); + } + + + // Compute CRC32C function. + address generate_CRC32C_updateBytes(const char* name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + unsigned int start_off = __ offset(); // Remember stub start address (is rtn value). + + assert(UseCRC32CIntrinsics, "should not generate this stub (%s) with CRC32C intrinsics disabled", name); + + BLOCK_COMMENT("CRC32C_updateBytes {"); + Register table = Z_ARG4; // crc32c table address. + StubRoutines::zarch::generate_load_crc32c_table_addr(_masm, table); + + generate_CRC_updateBytes(name, table, false); + BLOCK_COMMENT("} CRC32C_updateBytes"); return __ addr_at(start_off); } @@ -2441,9 +2431,13 @@ class StubGenerator: public StubCodeGenerator { // Entry points that are platform specific. if (UseCRC32Intrinsics) { - // We have no CRC32 table on z/Architecture. - StubRoutines::_crc_table_adr = (address)StubRoutines::zarch::_crc_table; - StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes("CRC32_updateBytes"); + StubRoutines::_crc_table_adr = (address)StubRoutines::zarch::_crc_table; + StubRoutines::_updateBytesCRC32 = generate_CRC32_updateBytes("CRC32_updateBytes"); + } + + if (UseCRC32CIntrinsics) { + StubRoutines::_crc32c_table_addr = (address)StubRoutines::zarch::_crc32c_table; + StubRoutines::_updateBytesCRC32C = generate_CRC32C_updateBytes("CRC32C_updateBytes"); } // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. @@ -2461,8 +2455,6 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_throw_IncompatibleClassChangeError_entry= generate_throw_exception("IncompatibleClassChangeError throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_IncompatibleClassChangeError), false); StubRoutines::_throw_NullPointerException_at_call_entry= generate_throw_exception("NullPointerException at call throw_exception", CAST_FROM_FN_PTR(address, SharedRuntime::throw_NullPointerException_at_call), false); - StubRoutines::zarch::_handler_for_unsafe_access_entry = generate_handler_for_unsafe_access(); - // Support for verify_oop (must happen after universe_init). StubRoutines::_verify_oop_subroutine_entry = generate_verify_oop_subroutine(); diff --git a/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp b/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp index 8c60ae04350..ab167d9030f 100644 --- a/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp +++ b/hotspot/src/cpu/s390/vm/stubRoutines_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. 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 @@ -33,8 +33,6 @@ // Implementation of the platform-specific part of StubRoutines - for // a description of how to extend it, see the stubRoutines.hpp file. -address StubRoutines::zarch::_handler_for_unsafe_access_entry = NULL; - address StubRoutines::zarch::_partial_subtype_check = NULL; // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. @@ -44,14 +42,15 @@ int StubRoutines::zarch::_atomic_memory_operation_lock = StubRoutines::zarch::un #define __ masm-> -void StubRoutines::zarch::generate_load_crc_table_addr(MacroAssembler* masm, Register table) { +void StubRoutines::zarch::generate_load_absolute_address(MacroAssembler* masm, Register table, address table_addr, uint64_t table_contents) { + __ load_absolute_address(table, table_addr); - __ load_absolute_address(table, StubRoutines::_crc_table_adr); #ifdef ASSERT - assert(_crc_table_adr != NULL, "CRC lookup table address must be initialized by now"); + assert(table_addr != NULL, "CRC lookup table address must be initialized by now"); + assert(*((uint32_t*)(table_addr+4)) == (uint32_t)table_contents, "Bad CRC lookup table: 0x%8.8x, expected 0x%8.8x", *((uint32_t*)(table_addr+4)), (uint32_t)table_contents); { Label L; - __ load_const_optimized(Z_R0, StubRoutines::_crc_table_adr); + __ load_const_optimized(Z_R0, table_addr); __ z_cgr(table, Z_R0); // safety net __ z_bre(L); __ z_illtrap(); @@ -60,7 +59,7 @@ void StubRoutines::zarch::generate_load_crc_table_addr(MacroAssembler* masm, Reg } { Label L; - __ load_const_optimized(Z_R0, 0x77073096UL); + __ load_const_optimized(Z_R0, table_contents); // crc_table: data @ offset(4) __ z_cl(Z_R0, Address(table, 4)); // safety net __ z_bre(L); __ z_l(Z_R0, Address(table, 4)); // Load data from memory, we know the constant we compared against. @@ -71,6 +70,17 @@ void StubRoutines::zarch::generate_load_crc_table_addr(MacroAssembler* masm, Reg #endif } +void StubRoutines::zarch::generate_load_crc_table_addr(MacroAssembler* masm, Register table) { + const uint64_t table_contents = 0x77073096UL; // required contents of table[1] + generate_load_absolute_address(masm, table, StubRoutines::_crc_table_adr, table_contents); +} + +void StubRoutines::zarch::generate_load_crc32c_table_addr(MacroAssembler* masm, Register table) { + const uint64_t table_contents = 0xf26b8303UL; // required contents of table[1] + generate_load_absolute_address(masm, table, StubRoutines::_crc32c_table_addr, table_contents); +} + + // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. void StubRoutines::zarch::generate_load_trot_table_addr(MacroAssembler* masm, Register table) { @@ -130,440 +140,590 @@ jlong StubRoutines::zarch::_trot_table[TROT_COLUMN_SIZE] = { }; -// crc_table[] from jdk/src/share/native/java/util/zip/zlib-1.2.8/crc32.h juint StubRoutines::zarch::_crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE] = { - { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL -#ifdef CRC32_BYFOUR - }, - { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, - 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, - 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, - 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, - 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, - 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, - 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, - 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, - 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, - 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, - 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, - 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, - 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, - 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, - 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, - 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, - 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, - 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, - 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, - 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, - 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, - 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, - 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, - 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, - 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, - 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, - 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, - 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, - 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, - 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, - 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, - 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, - 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, - 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, - 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, - 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, - 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, - 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, - 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, - 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, - 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, - 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, - 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, - 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, - 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, - 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, - 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, - 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, - 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, - 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, - 0x9324fd72UL - }, - { - 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, - 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, - 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, - 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, - 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, - 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, - 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, - 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, - 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, - 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, - 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, - 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, - 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, - 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, - 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, - 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, - 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, - 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, - 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, - 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, - 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, - 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, - 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, - 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, - 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, - 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, - 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, - 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, - 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, - 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, - 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, - 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, - 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, - 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, - 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, - 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, - 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, - 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, - 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, - 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, - 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, - 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, - 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, - 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, - 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, - 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, - 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, - 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, - 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, - 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, - 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, - 0xbe9834edUL - }, - { - 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, - 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, - 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, - 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, - 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, - 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, - 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, - 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, - 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, - 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, - 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, - 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, - 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, - 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, - 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, - 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, - 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, - 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, - 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, - 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, - 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, - 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, - 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, - 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, - 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, - 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, - 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, - 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, - 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, - 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, - 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, - 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, - 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, - 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, - 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, - 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, - 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, - 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, - 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, - 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, - 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, - 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, - 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, - 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, - 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, - 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, - 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, - 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, - 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, - 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, - 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, - 0xde0506f1UL - }, - { - 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, - 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, - 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, - 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, - 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, - 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, - 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, - 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, - 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, - 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, - 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, - 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, - 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, - 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, - 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, - 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, - 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, - 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, - 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, - 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, - 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, - 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, - 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, - 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, - 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, - 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, - 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, - 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, - 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, - 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, - 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, - 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, - 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, - 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, - 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, - 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, - 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, - 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, - 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, - 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, - 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, - 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, - 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, - 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, - 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, - 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, - 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, - 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, - 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, - 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, - 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, - 0x8def022dUL - }, - { - 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, - 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, - 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, - 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, - 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, - 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, - 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, - 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, - 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, - 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, - 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, - 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, - 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, - 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, - 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, - 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, - 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, - 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, - 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, - 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, - 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, - 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, - 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, - 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, - 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, - 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, - 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, - 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, - 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, - 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, - 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, - 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, - 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, - 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, - 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, - 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, - 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, - 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, - 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, - 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, - 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, - 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, - 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, - 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, - 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, - 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, - 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, - 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, - 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, - 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, - 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, - 0x72fd2493UL - }, - { - 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, - 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, - 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, - 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, - 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, - 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, - 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, - 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, - 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, - 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, - 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, - 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, - 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, - 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, - 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, - 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, - 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, - 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, - 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, - 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, - 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, - 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, - 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, - 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, - 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, - 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, - 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, - 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, - 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, - 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, - 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, - 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, - 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, - 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, - 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, - 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, - 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, - 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, - 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, - 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, - 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, - 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, - 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, - 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, - 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, - 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, - 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, - 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, - 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, - 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, - 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, - 0xed3498beUL - }, - { - 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, - 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, - 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, - 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, - 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, - 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, - 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, - 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, - 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, - 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, - 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, - 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, - 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, - 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, - 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, - 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, - 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, - 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, - 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, - 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, - 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, - 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, - 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, - 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, - 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, - 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, - 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, - 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, - 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, - 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, - 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, - 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, - 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, - 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, - 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, - 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, - 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, - 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, - 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, - 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, - 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, - 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, - 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, - 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, - 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, - 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, - 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, - 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, - 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, - 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, - 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, - 0xf10605deUL -#endif - } -}; + /* polyBits = 7976584769 0x00000001db710641L, shifted = 0xedb88320 */ + /* CRC32 table for single bytes, auto-generated. DO NOT MODIFY! */ + /* CRC32 table 0 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 0x706af48fU, 0xe963a535U, 0x9e6495a3U + /* 8 */ , 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U, 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U + /* 16 */ , 0x1db71064U, 0x6ab020f2U, 0xf3b97148U, 0x84be41deU, 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U + /* 24 */ , 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U, 0xfa0f3d63U, 0x8d080df5U + /* 32 */ , 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa2677172U, 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU + /* 40 */ , 0x35b5a8faU, 0x42b2986cU, 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U + /* 48 */ , 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U, 0xcfba9599U, 0xb8bda50fU + /* 56 */ , 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U, 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU + /* 64 */ , 0x76dc4190U, 0x01db7106U, 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, 0xe8b8d433U + /* 72 */ , 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU, 0x91646c97U, 0xe6635c01U + /* 80 */ , 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU, 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U + /* 88 */ , 0x65b0d9c6U, 0x12b7e950U, 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U + /* 96 */ , 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x3dd895d7U, 0xa4d1c46dU, 0xd3d6f4fbU + /* 104 */ , 0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U, 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U + /* 112 */ , 0x5005713cU, 0x270241aaU, 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU + /* 120 */ , 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x2eb40d81U, 0xb7bd5c3bU, 0xc0ba6cadU + /* 128 */ , 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU, 0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U + /* 136 */ , 0xe3630b12U, 0x94643b84U, 0x0d6d6a3eU, 0x7a6a5aa8U, 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U + /* 144 */ , 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU, 0x196c3671U, 0x6e6b06e7U + /* 152 */ , 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x67dd4accU, 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U + /* 160 */ , 0xd6d6a3e8U, 0xa1d1937eU, 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU + /* 168 */ , 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U, 0x316e8eefU, 0x4669be79U + /* 176 */ , 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U, 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU + /* 184 */ , 0xc5ba3bbeU, 0xb2bd0b28U, 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bdeae1dU + /* 192 */ , 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU, 0x72076785U, 0x05005713U + /* 200 */ , 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U, 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U + /* 208 */ , 0x86d3d2d4U, 0xf1d4e242U, 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b74777U + /* 216 */ , 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, 0xf862ae69U, 0x616bffd3U, 0x166ccf45U + /* 224 */ , 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U, 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU + /* 232 */ , 0xaed16a4aU, 0xd9d65adcU, 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U + /* 240 */ , 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, 0xcdd70693U, 0x54de5729U, 0x23d967bfU + /* 248 */ , 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f2b94U, 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU + } + #ifdef CRC32_BYFOUR + , + /* CRC32 table 1 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x191b3141U, 0x32366282U, 0x2b2d53c3U, 0x646cc504U, 0x7d77f445U, 0x565aa786U, 0x4f4196c7U + /* 8 */ , 0xc8d98a08U, 0xd1c2bb49U, 0xfaefe88aU, 0xe3f4d9cbU, 0xacb54f0cU, 0xb5ae7e4dU, 0x9e832d8eU, 0x87981ccfU + /* 16 */ , 0x4ac21251U, 0x53d92310U, 0x78f470d3U, 0x61ef4192U, 0x2eaed755U, 0x37b5e614U, 0x1c98b5d7U, 0x05838496U + /* 24 */ , 0x821b9859U, 0x9b00a918U, 0xb02dfadbU, 0xa936cb9aU, 0xe6775d5dU, 0xff6c6c1cU, 0xd4413fdfU, 0xcd5a0e9eU + /* 32 */ , 0x958424a2U, 0x8c9f15e3U, 0xa7b24620U, 0xbea97761U, 0xf1e8e1a6U, 0xe8f3d0e7U, 0xc3de8324U, 0xdac5b265U + /* 40 */ , 0x5d5daeaaU, 0x44469febU, 0x6f6bcc28U, 0x7670fd69U, 0x39316baeU, 0x202a5aefU, 0x0b07092cU, 0x121c386dU + /* 48 */ , 0xdf4636f3U, 0xc65d07b2U, 0xed705471U, 0xf46b6530U, 0xbb2af3f7U, 0xa231c2b6U, 0x891c9175U, 0x9007a034U + /* 56 */ , 0x179fbcfbU, 0x0e848dbaU, 0x25a9de79U, 0x3cb2ef38U, 0x73f379ffU, 0x6ae848beU, 0x41c51b7dU, 0x58de2a3cU + /* 64 */ , 0xf0794f05U, 0xe9627e44U, 0xc24f2d87U, 0xdb541cc6U, 0x94158a01U, 0x8d0ebb40U, 0xa623e883U, 0xbf38d9c2U + /* 72 */ , 0x38a0c50dU, 0x21bbf44cU, 0x0a96a78fU, 0x138d96ceU, 0x5ccc0009U, 0x45d73148U, 0x6efa628bU, 0x77e153caU + /* 80 */ , 0xbabb5d54U, 0xa3a06c15U, 0x888d3fd6U, 0x91960e97U, 0xded79850U, 0xc7cca911U, 0xece1fad2U, 0xf5facb93U + /* 88 */ , 0x7262d75cU, 0x6b79e61dU, 0x4054b5deU, 0x594f849fU, 0x160e1258U, 0x0f152319U, 0x243870daU, 0x3d23419bU + /* 96 */ , 0x65fd6ba7U, 0x7ce65ae6U, 0x57cb0925U, 0x4ed03864U, 0x0191aea3U, 0x188a9fe2U, 0x33a7cc21U, 0x2abcfd60U + /* 104 */ , 0xad24e1afU, 0xb43fd0eeU, 0x9f12832dU, 0x8609b26cU, 0xc94824abU, 0xd05315eaU, 0xfb7e4629U, 0xe2657768U + /* 112 */ , 0x2f3f79f6U, 0x362448b7U, 0x1d091b74U, 0x04122a35U, 0x4b53bcf2U, 0x52488db3U, 0x7965de70U, 0x607eef31U + /* 120 */ , 0xe7e6f3feU, 0xfefdc2bfU, 0xd5d0917cU, 0xcccba03dU, 0x838a36faU, 0x9a9107bbU, 0xb1bc5478U, 0xa8a76539U + /* 128 */ , 0x3b83984bU, 0x2298a90aU, 0x09b5fac9U, 0x10aecb88U, 0x5fef5d4fU, 0x46f46c0eU, 0x6dd93fcdU, 0x74c20e8cU + /* 136 */ , 0xf35a1243U, 0xea412302U, 0xc16c70c1U, 0xd8774180U, 0x9736d747U, 0x8e2de606U, 0xa500b5c5U, 0xbc1b8484U + /* 144 */ , 0x71418a1aU, 0x685abb5bU, 0x4377e898U, 0x5a6cd9d9U, 0x152d4f1eU, 0x0c367e5fU, 0x271b2d9cU, 0x3e001cddU + /* 152 */ , 0xb9980012U, 0xa0833153U, 0x8bae6290U, 0x92b553d1U, 0xddf4c516U, 0xc4eff457U, 0xefc2a794U, 0xf6d996d5U + /* 160 */ , 0xae07bce9U, 0xb71c8da8U, 0x9c31de6bU, 0x852aef2aU, 0xca6b79edU, 0xd37048acU, 0xf85d1b6fU, 0xe1462a2eU + /* 168 */ , 0x66de36e1U, 0x7fc507a0U, 0x54e85463U, 0x4df36522U, 0x02b2f3e5U, 0x1ba9c2a4U, 0x30849167U, 0x299fa026U + /* 176 */ , 0xe4c5aeb8U, 0xfdde9ff9U, 0xd6f3cc3aU, 0xcfe8fd7bU, 0x80a96bbcU, 0x99b25afdU, 0xb29f093eU, 0xab84387fU + /* 184 */ , 0x2c1c24b0U, 0x350715f1U, 0x1e2a4632U, 0x07317773U, 0x4870e1b4U, 0x516bd0f5U, 0x7a468336U, 0x635db277U + /* 192 */ , 0xcbfad74eU, 0xd2e1e60fU, 0xf9ccb5ccU, 0xe0d7848dU, 0xaf96124aU, 0xb68d230bU, 0x9da070c8U, 0x84bb4189U + /* 200 */ , 0x03235d46U, 0x1a386c07U, 0x31153fc4U, 0x280e0e85U, 0x674f9842U, 0x7e54a903U, 0x5579fac0U, 0x4c62cb81U + /* 208 */ , 0x8138c51fU, 0x9823f45eU, 0xb30ea79dU, 0xaa1596dcU, 0xe554001bU, 0xfc4f315aU, 0xd7626299U, 0xce7953d8U + /* 216 */ , 0x49e14f17U, 0x50fa7e56U, 0x7bd72d95U, 0x62cc1cd4U, 0x2d8d8a13U, 0x3496bb52U, 0x1fbbe891U, 0x06a0d9d0U + /* 224 */ , 0x5e7ef3ecU, 0x4765c2adU, 0x6c48916eU, 0x7553a02fU, 0x3a1236e8U, 0x230907a9U, 0x0824546aU, 0x113f652bU + /* 232 */ , 0x96a779e4U, 0x8fbc48a5U, 0xa4911b66U, 0xbd8a2a27U, 0xf2cbbce0U, 0xebd08da1U, 0xc0fdde62U, 0xd9e6ef23U + /* 240 */ , 0x14bce1bdU, 0x0da7d0fcU, 0x268a833fU, 0x3f91b27eU, 0x70d024b9U, 0x69cb15f8U, 0x42e6463bU, 0x5bfd777aU + /* 248 */ , 0xdc656bb5U, 0xc57e5af4U, 0xee530937U, 0xf7483876U, 0xb809aeb1U, 0xa1129ff0U, 0x8a3fcc33U, 0x9324fd72U + } + , + /* CRC32 table 2 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x01c26a37U, 0x0384d46eU, 0x0246be59U, 0x0709a8dcU, 0x06cbc2ebU, 0x048d7cb2U, 0x054f1685U + /* 8 */ , 0x0e1351b8U, 0x0fd13b8fU, 0x0d9785d6U, 0x0c55efe1U, 0x091af964U, 0x08d89353U, 0x0a9e2d0aU, 0x0b5c473dU + /* 16 */ , 0x1c26a370U, 0x1de4c947U, 0x1fa2771eU, 0x1e601d29U, 0x1b2f0bacU, 0x1aed619bU, 0x18abdfc2U, 0x1969b5f5U + /* 24 */ , 0x1235f2c8U, 0x13f798ffU, 0x11b126a6U, 0x10734c91U, 0x153c5a14U, 0x14fe3023U, 0x16b88e7aU, 0x177ae44dU + /* 32 */ , 0x384d46e0U, 0x398f2cd7U, 0x3bc9928eU, 0x3a0bf8b9U, 0x3f44ee3cU, 0x3e86840bU, 0x3cc03a52U, 0x3d025065U + /* 40 */ , 0x365e1758U, 0x379c7d6fU, 0x35dac336U, 0x3418a901U, 0x3157bf84U, 0x3095d5b3U, 0x32d36beaU, 0x331101ddU + /* 48 */ , 0x246be590U, 0x25a98fa7U, 0x27ef31feU, 0x262d5bc9U, 0x23624d4cU, 0x22a0277bU, 0x20e69922U, 0x2124f315U + /* 56 */ , 0x2a78b428U, 0x2bbade1fU, 0x29fc6046U, 0x283e0a71U, 0x2d711cf4U, 0x2cb376c3U, 0x2ef5c89aU, 0x2f37a2adU + /* 64 */ , 0x709a8dc0U, 0x7158e7f7U, 0x731e59aeU, 0x72dc3399U, 0x7793251cU, 0x76514f2bU, 0x7417f172U, 0x75d59b45U + /* 72 */ , 0x7e89dc78U, 0x7f4bb64fU, 0x7d0d0816U, 0x7ccf6221U, 0x798074a4U, 0x78421e93U, 0x7a04a0caU, 0x7bc6cafdU + /* 80 */ , 0x6cbc2eb0U, 0x6d7e4487U, 0x6f38fadeU, 0x6efa90e9U, 0x6bb5866cU, 0x6a77ec5bU, 0x68315202U, 0x69f33835U + /* 88 */ , 0x62af7f08U, 0x636d153fU, 0x612bab66U, 0x60e9c151U, 0x65a6d7d4U, 0x6464bde3U, 0x662203baU, 0x67e0698dU + /* 96 */ , 0x48d7cb20U, 0x4915a117U, 0x4b531f4eU, 0x4a917579U, 0x4fde63fcU, 0x4e1c09cbU, 0x4c5ab792U, 0x4d98dda5U + /* 104 */ , 0x46c49a98U, 0x4706f0afU, 0x45404ef6U, 0x448224c1U, 0x41cd3244U, 0x400f5873U, 0x4249e62aU, 0x438b8c1dU + /* 112 */ , 0x54f16850U, 0x55330267U, 0x5775bc3eU, 0x56b7d609U, 0x53f8c08cU, 0x523aaabbU, 0x507c14e2U, 0x51be7ed5U + /* 120 */ , 0x5ae239e8U, 0x5b2053dfU, 0x5966ed86U, 0x58a487b1U, 0x5deb9134U, 0x5c29fb03U, 0x5e6f455aU, 0x5fad2f6dU + /* 128 */ , 0xe1351b80U, 0xe0f771b7U, 0xe2b1cfeeU, 0xe373a5d9U, 0xe63cb35cU, 0xe7fed96bU, 0xe5b86732U, 0xe47a0d05U + /* 136 */ , 0xef264a38U, 0xeee4200fU, 0xeca29e56U, 0xed60f461U, 0xe82fe2e4U, 0xe9ed88d3U, 0xebab368aU, 0xea695cbdU + /* 144 */ , 0xfd13b8f0U, 0xfcd1d2c7U, 0xfe976c9eU, 0xff5506a9U, 0xfa1a102cU, 0xfbd87a1bU, 0xf99ec442U, 0xf85cae75U + /* 152 */ , 0xf300e948U, 0xf2c2837fU, 0xf0843d26U, 0xf1465711U, 0xf4094194U, 0xf5cb2ba3U, 0xf78d95faU, 0xf64fffcdU + /* 160 */ , 0xd9785d60U, 0xd8ba3757U, 0xdafc890eU, 0xdb3ee339U, 0xde71f5bcU, 0xdfb39f8bU, 0xddf521d2U, 0xdc374be5U + /* 168 */ , 0xd76b0cd8U, 0xd6a966efU, 0xd4efd8b6U, 0xd52db281U, 0xd062a404U, 0xd1a0ce33U, 0xd3e6706aU, 0xd2241a5dU + /* 176 */ , 0xc55efe10U, 0xc49c9427U, 0xc6da2a7eU, 0xc7184049U, 0xc25756ccU, 0xc3953cfbU, 0xc1d382a2U, 0xc011e895U + /* 184 */ , 0xcb4dafa8U, 0xca8fc59fU, 0xc8c97bc6U, 0xc90b11f1U, 0xcc440774U, 0xcd866d43U, 0xcfc0d31aU, 0xce02b92dU + /* 192 */ , 0x91af9640U, 0x906dfc77U, 0x922b422eU, 0x93e92819U, 0x96a63e9cU, 0x976454abU, 0x9522eaf2U, 0x94e080c5U + /* 200 */ , 0x9fbcc7f8U, 0x9e7eadcfU, 0x9c381396U, 0x9dfa79a1U, 0x98b56f24U, 0x99770513U, 0x9b31bb4aU, 0x9af3d17dU + /* 208 */ , 0x8d893530U, 0x8c4b5f07U, 0x8e0de15eU, 0x8fcf8b69U, 0x8a809decU, 0x8b42f7dbU, 0x89044982U, 0x88c623b5U + /* 216 */ , 0x839a6488U, 0x82580ebfU, 0x801eb0e6U, 0x81dcdad1U, 0x8493cc54U, 0x8551a663U, 0x8717183aU, 0x86d5720dU + /* 224 */ , 0xa9e2d0a0U, 0xa820ba97U, 0xaa6604ceU, 0xaba46ef9U, 0xaeeb787cU, 0xaf29124bU, 0xad6fac12U, 0xacadc625U + /* 232 */ , 0xa7f18118U, 0xa633eb2fU, 0xa4755576U, 0xa5b73f41U, 0xa0f829c4U, 0xa13a43f3U, 0xa37cfdaaU, 0xa2be979dU + /* 240 */ , 0xb5c473d0U, 0xb40619e7U, 0xb640a7beU, 0xb782cd89U, 0xb2cddb0cU, 0xb30fb13bU, 0xb1490f62U, 0xb08b6555U + /* 248 */ , 0xbbd72268U, 0xba15485fU, 0xb853f606U, 0xb9919c31U, 0xbcde8ab4U, 0xbd1ce083U, 0xbf5a5edaU, 0xbe9834edU + } + , + /* CRC32 table 3 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xb8bc6765U, 0xaa09c88bU, 0x12b5afeeU, 0x8f629757U, 0x37def032U, 0x256b5fdcU, 0x9dd738b9U + /* 8 */ , 0xc5b428efU, 0x7d084f8aU, 0x6fbde064U, 0xd7018701U, 0x4ad6bfb8U, 0xf26ad8ddU, 0xe0df7733U, 0x58631056U + /* 16 */ , 0x5019579fU, 0xe8a530faU, 0xfa109f14U, 0x42acf871U, 0xdf7bc0c8U, 0x67c7a7adU, 0x75720843U, 0xcdce6f26U + /* 24 */ , 0x95ad7f70U, 0x2d111815U, 0x3fa4b7fbU, 0x8718d09eU, 0x1acfe827U, 0xa2738f42U, 0xb0c620acU, 0x087a47c9U + /* 32 */ , 0xa032af3eU, 0x188ec85bU, 0x0a3b67b5U, 0xb28700d0U, 0x2f503869U, 0x97ec5f0cU, 0x8559f0e2U, 0x3de59787U + /* 40 */ , 0x658687d1U, 0xdd3ae0b4U, 0xcf8f4f5aU, 0x7733283fU, 0xeae41086U, 0x525877e3U, 0x40edd80dU, 0xf851bf68U + /* 48 */ , 0xf02bf8a1U, 0x48979fc4U, 0x5a22302aU, 0xe29e574fU, 0x7f496ff6U, 0xc7f50893U, 0xd540a77dU, 0x6dfcc018U + /* 56 */ , 0x359fd04eU, 0x8d23b72bU, 0x9f9618c5U, 0x272a7fa0U, 0xbafd4719U, 0x0241207cU, 0x10f48f92U, 0xa848e8f7U + /* 64 */ , 0x9b14583dU, 0x23a83f58U, 0x311d90b6U, 0x89a1f7d3U, 0x1476cf6aU, 0xaccaa80fU, 0xbe7f07e1U, 0x06c36084U + /* 72 */ , 0x5ea070d2U, 0xe61c17b7U, 0xf4a9b859U, 0x4c15df3cU, 0xd1c2e785U, 0x697e80e0U, 0x7bcb2f0eU, 0xc377486bU + /* 80 */ , 0xcb0d0fa2U, 0x73b168c7U, 0x6104c729U, 0xd9b8a04cU, 0x446f98f5U, 0xfcd3ff90U, 0xee66507eU, 0x56da371bU + /* 88 */ , 0x0eb9274dU, 0xb6054028U, 0xa4b0efc6U, 0x1c0c88a3U, 0x81dbb01aU, 0x3967d77fU, 0x2bd27891U, 0x936e1ff4U + /* 96 */ , 0x3b26f703U, 0x839a9066U, 0x912f3f88U, 0x299358edU, 0xb4446054U, 0x0cf80731U, 0x1e4da8dfU, 0xa6f1cfbaU + /* 104 */ , 0xfe92dfecU, 0x462eb889U, 0x549b1767U, 0xec277002U, 0x71f048bbU, 0xc94c2fdeU, 0xdbf98030U, 0x6345e755U + /* 112 */ , 0x6b3fa09cU, 0xd383c7f9U, 0xc1366817U, 0x798a0f72U, 0xe45d37cbU, 0x5ce150aeU, 0x4e54ff40U, 0xf6e89825U + /* 120 */ , 0xae8b8873U, 0x1637ef16U, 0x048240f8U, 0xbc3e279dU, 0x21e91f24U, 0x99557841U, 0x8be0d7afU, 0x335cb0caU + /* 128 */ , 0xed59b63bU, 0x55e5d15eU, 0x47507eb0U, 0xffec19d5U, 0x623b216cU, 0xda874609U, 0xc832e9e7U, 0x708e8e82U + /* 136 */ , 0x28ed9ed4U, 0x9051f9b1U, 0x82e4565fU, 0x3a58313aU, 0xa78f0983U, 0x1f336ee6U, 0x0d86c108U, 0xb53aa66dU + /* 144 */ , 0xbd40e1a4U, 0x05fc86c1U, 0x1749292fU, 0xaff54e4aU, 0x322276f3U, 0x8a9e1196U, 0x982bbe78U, 0x2097d91dU + /* 152 */ , 0x78f4c94bU, 0xc048ae2eU, 0xd2fd01c0U, 0x6a4166a5U, 0xf7965e1cU, 0x4f2a3979U, 0x5d9f9697U, 0xe523f1f2U + /* 160 */ , 0x4d6b1905U, 0xf5d77e60U, 0xe762d18eU, 0x5fdeb6ebU, 0xc2098e52U, 0x7ab5e937U, 0x680046d9U, 0xd0bc21bcU + /* 168 */ , 0x88df31eaU, 0x3063568fU, 0x22d6f961U, 0x9a6a9e04U, 0x07bda6bdU, 0xbf01c1d8U, 0xadb46e36U, 0x15080953U + /* 176 */ , 0x1d724e9aU, 0xa5ce29ffU, 0xb77b8611U, 0x0fc7e174U, 0x9210d9cdU, 0x2aacbea8U, 0x38191146U, 0x80a57623U + /* 184 */ , 0xd8c66675U, 0x607a0110U, 0x72cfaefeU, 0xca73c99bU, 0x57a4f122U, 0xef189647U, 0xfdad39a9U, 0x45115eccU + /* 192 */ , 0x764dee06U, 0xcef18963U, 0xdc44268dU, 0x64f841e8U, 0xf92f7951U, 0x41931e34U, 0x5326b1daU, 0xeb9ad6bfU + /* 200 */ , 0xb3f9c6e9U, 0x0b45a18cU, 0x19f00e62U, 0xa14c6907U, 0x3c9b51beU, 0x842736dbU, 0x96929935U, 0x2e2efe50U + /* 208 */ , 0x2654b999U, 0x9ee8defcU, 0x8c5d7112U, 0x34e11677U, 0xa9362eceU, 0x118a49abU, 0x033fe645U, 0xbb838120U + /* 216 */ , 0xe3e09176U, 0x5b5cf613U, 0x49e959fdU, 0xf1553e98U, 0x6c820621U, 0xd43e6144U, 0xc68bceaaU, 0x7e37a9cfU + /* 224 */ , 0xd67f4138U, 0x6ec3265dU, 0x7c7689b3U, 0xc4caeed6U, 0x591dd66fU, 0xe1a1b10aU, 0xf3141ee4U, 0x4ba87981U + /* 232 */ , 0x13cb69d7U, 0xab770eb2U, 0xb9c2a15cU, 0x017ec639U, 0x9ca9fe80U, 0x241599e5U, 0x36a0360bU, 0x8e1c516eU + /* 240 */ , 0x866616a7U, 0x3eda71c2U, 0x2c6fde2cU, 0x94d3b949U, 0x090481f0U, 0xb1b8e695U, 0xa30d497bU, 0x1bb12e1eU + /* 248 */ , 0x43d23e48U, 0xfb6e592dU, 0xe9dbf6c3U, 0x516791a6U, 0xccb0a91fU, 0x740cce7aU, 0x66b96194U, 0xde0506f1U + } + , + /* CRC32 table 4 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x96300777U, 0x2c610eeeU, 0xba510999U, 0x19c46d07U, 0x8ff46a70U, 0x35a563e9U, 0xa395649eU + /* 8 */ , 0x3288db0eU, 0xa4b8dc79U, 0x1ee9d5e0U, 0x88d9d297U, 0x2b4cb609U, 0xbd7cb17eU, 0x072db8e7U, 0x911dbf90U + /* 16 */ , 0x6410b71dU, 0xf220b06aU, 0x4871b9f3U, 0xde41be84U, 0x7dd4da1aU, 0xebe4dd6dU, 0x51b5d4f4U, 0xc785d383U + /* 24 */ , 0x56986c13U, 0xc0a86b64U, 0x7af962fdU, 0xecc9658aU, 0x4f5c0114U, 0xd96c0663U, 0x633d0ffaU, 0xf50d088dU + /* 32 */ , 0xc8206e3bU, 0x5e10694cU, 0xe44160d5U, 0x727167a2U, 0xd1e4033cU, 0x47d4044bU, 0xfd850dd2U, 0x6bb50aa5U + /* 40 */ , 0xfaa8b535U, 0x6c98b242U, 0xd6c9bbdbU, 0x40f9bcacU, 0xe36cd832U, 0x755cdf45U, 0xcf0dd6dcU, 0x593dd1abU + /* 48 */ , 0xac30d926U, 0x3a00de51U, 0x8051d7c8U, 0x1661d0bfU, 0xb5f4b421U, 0x23c4b356U, 0x9995bacfU, 0x0fa5bdb8U + /* 56 */ , 0x9eb80228U, 0x0888055fU, 0xb2d90cc6U, 0x24e90bb1U, 0x877c6f2fU, 0x114c6858U, 0xab1d61c1U, 0x3d2d66b6U + /* 64 */ , 0x9041dc76U, 0x0671db01U, 0xbc20d298U, 0x2a10d5efU, 0x8985b171U, 0x1fb5b606U, 0xa5e4bf9fU, 0x33d4b8e8U + /* 72 */ , 0xa2c90778U, 0x34f9000fU, 0x8ea80996U, 0x18980ee1U, 0xbb0d6a7fU, 0x2d3d6d08U, 0x976c6491U, 0x015c63e6U + /* 80 */ , 0xf4516b6bU, 0x62616c1cU, 0xd8306585U, 0x4e0062f2U, 0xed95066cU, 0x7ba5011bU, 0xc1f40882U, 0x57c40ff5U + /* 88 */ , 0xc6d9b065U, 0x50e9b712U, 0xeab8be8bU, 0x7c88b9fcU, 0xdf1ddd62U, 0x492dda15U, 0xf37cd38cU, 0x654cd4fbU + /* 96 */ , 0x5861b24dU, 0xce51b53aU, 0x7400bca3U, 0xe230bbd4U, 0x41a5df4aU, 0xd795d83dU, 0x6dc4d1a4U, 0xfbf4d6d3U + /* 104 */ , 0x6ae96943U, 0xfcd96e34U, 0x468867adU, 0xd0b860daU, 0x732d0444U, 0xe51d0333U, 0x5f4c0aaaU, 0xc97c0dddU + /* 112 */ , 0x3c710550U, 0xaa410227U, 0x10100bbeU, 0x86200cc9U, 0x25b56857U, 0xb3856f20U, 0x09d466b9U, 0x9fe461ceU + /* 120 */ , 0x0ef9de5eU, 0x98c9d929U, 0x2298d0b0U, 0xb4a8d7c7U, 0x173db359U, 0x810db42eU, 0x3b5cbdb7U, 0xad6cbac0U + /* 128 */ , 0x2083b8edU, 0xb6b3bf9aU, 0x0ce2b603U, 0x9ad2b174U, 0x3947d5eaU, 0xaf77d29dU, 0x1526db04U, 0x8316dc73U + /* 136 */ , 0x120b63e3U, 0x843b6494U, 0x3e6a6d0dU, 0xa85a6a7aU, 0x0bcf0ee4U, 0x9dff0993U, 0x27ae000aU, 0xb19e077dU + /* 144 */ , 0x44930ff0U, 0xd2a30887U, 0x68f2011eU, 0xfec20669U, 0x5d5762f7U, 0xcb676580U, 0x71366c19U, 0xe7066b6eU + /* 152 */ , 0x761bd4feU, 0xe02bd389U, 0x5a7ada10U, 0xcc4add67U, 0x6fdfb9f9U, 0xf9efbe8eU, 0x43beb717U, 0xd58eb060U + /* 160 */ , 0xe8a3d6d6U, 0x7e93d1a1U, 0xc4c2d838U, 0x52f2df4fU, 0xf167bbd1U, 0x6757bca6U, 0xdd06b53fU, 0x4b36b248U + /* 168 */ , 0xda2b0dd8U, 0x4c1b0aafU, 0xf64a0336U, 0x607a0441U, 0xc3ef60dfU, 0x55df67a8U, 0xef8e6e31U, 0x79be6946U + /* 176 */ , 0x8cb361cbU, 0x1a8366bcU, 0xa0d26f25U, 0x36e26852U, 0x95770cccU, 0x03470bbbU, 0xb9160222U, 0x2f260555U + /* 184 */ , 0xbe3bbac5U, 0x280bbdb2U, 0x925ab42bU, 0x046ab35cU, 0xa7ffd7c2U, 0x31cfd0b5U, 0x8b9ed92cU, 0x1daede5bU + /* 192 */ , 0xb0c2649bU, 0x26f263ecU, 0x9ca36a75U, 0x0a936d02U, 0xa906099cU, 0x3f360eebU, 0x85670772U, 0x13570005U + /* 200 */ , 0x824abf95U, 0x147ab8e2U, 0xae2bb17bU, 0x381bb60cU, 0x9b8ed292U, 0x0dbed5e5U, 0xb7efdc7cU, 0x21dfdb0bU + /* 208 */ , 0xd4d2d386U, 0x42e2d4f1U, 0xf8b3dd68U, 0x6e83da1fU, 0xcd16be81U, 0x5b26b9f6U, 0xe177b06fU, 0x7747b718U + /* 216 */ , 0xe65a0888U, 0x706a0fffU, 0xca3b0666U, 0x5c0b0111U, 0xff9e658fU, 0x69ae62f8U, 0xd3ff6b61U, 0x45cf6c16U + /* 224 */ , 0x78e20aa0U, 0xeed20dd7U, 0x5483044eU, 0xc2b30339U, 0x612667a7U, 0xf71660d0U, 0x4d476949U, 0xdb776e3eU + /* 232 */ , 0x4a6ad1aeU, 0xdc5ad6d9U, 0x660bdf40U, 0xf03bd837U, 0x53aebca9U, 0xc59ebbdeU, 0x7fcfb247U, 0xe9ffb530U + /* 240 */ , 0x1cf2bdbdU, 0x8ac2bacaU, 0x3093b353U, 0xa6a3b424U, 0x0536d0baU, 0x9306d7cdU, 0x2957de54U, 0xbf67d923U + /* 248 */ , 0x2e7a66b3U, 0xb84a61c4U, 0x021b685dU, 0x942b6f2aU, 0x37be0bb4U, 0xa18e0cc3U, 0x1bdf055aU, 0x8def022dU + } + , + /* CRC32 table 5 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x41311b19U, 0x82623632U, 0xc3532d2bU, 0x04c56c64U, 0x45f4777dU, 0x86a75a56U, 0xc796414fU + /* 8 */ , 0x088ad9c8U, 0x49bbc2d1U, 0x8ae8effaU, 0xcbd9f4e3U, 0x0c4fb5acU, 0x4d7eaeb5U, 0x8e2d839eU, 0xcf1c9887U + /* 16 */ , 0x5112c24aU, 0x1023d953U, 0xd370f478U, 0x9241ef61U, 0x55d7ae2eU, 0x14e6b537U, 0xd7b5981cU, 0x96848305U + /* 24 */ , 0x59981b82U, 0x18a9009bU, 0xdbfa2db0U, 0x9acb36a9U, 0x5d5d77e6U, 0x1c6c6cffU, 0xdf3f41d4U, 0x9e0e5acdU + /* 32 */ , 0xa2248495U, 0xe3159f8cU, 0x2046b2a7U, 0x6177a9beU, 0xa6e1e8f1U, 0xe7d0f3e8U, 0x2483dec3U, 0x65b2c5daU + /* 40 */ , 0xaaae5d5dU, 0xeb9f4644U, 0x28cc6b6fU, 0x69fd7076U, 0xae6b3139U, 0xef5a2a20U, 0x2c09070bU, 0x6d381c12U + /* 48 */ , 0xf33646dfU, 0xb2075dc6U, 0x715470edU, 0x30656bf4U, 0xf7f32abbU, 0xb6c231a2U, 0x75911c89U, 0x34a00790U + /* 56 */ , 0xfbbc9f17U, 0xba8d840eU, 0x79dea925U, 0x38efb23cU, 0xff79f373U, 0xbe48e86aU, 0x7d1bc541U, 0x3c2ade58U + /* 64 */ , 0x054f79f0U, 0x447e62e9U, 0x872d4fc2U, 0xc61c54dbU, 0x018a1594U, 0x40bb0e8dU, 0x83e823a6U, 0xc2d938bfU + /* 72 */ , 0x0dc5a038U, 0x4cf4bb21U, 0x8fa7960aU, 0xce968d13U, 0x0900cc5cU, 0x4831d745U, 0x8b62fa6eU, 0xca53e177U + /* 80 */ , 0x545dbbbaU, 0x156ca0a3U, 0xd63f8d88U, 0x970e9691U, 0x5098d7deU, 0x11a9ccc7U, 0xd2fae1ecU, 0x93cbfaf5U + /* 88 */ , 0x5cd76272U, 0x1de6796bU, 0xdeb55440U, 0x9f844f59U, 0x58120e16U, 0x1923150fU, 0xda703824U, 0x9b41233dU + /* 96 */ , 0xa76bfd65U, 0xe65ae67cU, 0x2509cb57U, 0x6438d04eU, 0xa3ae9101U, 0xe29f8a18U, 0x21cca733U, 0x60fdbc2aU + /* 104 */ , 0xafe124adU, 0xeed03fb4U, 0x2d83129fU, 0x6cb20986U, 0xab2448c9U, 0xea1553d0U, 0x29467efbU, 0x687765e2U + /* 112 */ , 0xf6793f2fU, 0xb7482436U, 0x741b091dU, 0x352a1204U, 0xf2bc534bU, 0xb38d4852U, 0x70de6579U, 0x31ef7e60U + /* 120 */ , 0xfef3e6e7U, 0xbfc2fdfeU, 0x7c91d0d5U, 0x3da0cbccU, 0xfa368a83U, 0xbb07919aU, 0x7854bcb1U, 0x3965a7a8U + /* 128 */ , 0x4b98833bU, 0x0aa99822U, 0xc9fab509U, 0x88cbae10U, 0x4f5def5fU, 0x0e6cf446U, 0xcd3fd96dU, 0x8c0ec274U + /* 136 */ , 0x43125af3U, 0x022341eaU, 0xc1706cc1U, 0x804177d8U, 0x47d73697U, 0x06e62d8eU, 0xc5b500a5U, 0x84841bbcU + /* 144 */ , 0x1a8a4171U, 0x5bbb5a68U, 0x98e87743U, 0xd9d96c5aU, 0x1e4f2d15U, 0x5f7e360cU, 0x9c2d1b27U, 0xdd1c003eU + /* 152 */ , 0x120098b9U, 0x533183a0U, 0x9062ae8bU, 0xd153b592U, 0x16c5f4ddU, 0x57f4efc4U, 0x94a7c2efU, 0xd596d9f6U + /* 160 */ , 0xe9bc07aeU, 0xa88d1cb7U, 0x6bde319cU, 0x2aef2a85U, 0xed796bcaU, 0xac4870d3U, 0x6f1b5df8U, 0x2e2a46e1U + /* 168 */ , 0xe136de66U, 0xa007c57fU, 0x6354e854U, 0x2265f34dU, 0xe5f3b202U, 0xa4c2a91bU, 0x67918430U, 0x26a09f29U + /* 176 */ , 0xb8aec5e4U, 0xf99fdefdU, 0x3accf3d6U, 0x7bfde8cfU, 0xbc6ba980U, 0xfd5ab299U, 0x3e099fb2U, 0x7f3884abU + /* 184 */ , 0xb0241c2cU, 0xf1150735U, 0x32462a1eU, 0x73773107U, 0xb4e17048U, 0xf5d06b51U, 0x3683467aU, 0x77b25d63U + /* 192 */ , 0x4ed7facbU, 0x0fe6e1d2U, 0xccb5ccf9U, 0x8d84d7e0U, 0x4a1296afU, 0x0b238db6U, 0xc870a09dU, 0x8941bb84U + /* 200 */ , 0x465d2303U, 0x076c381aU, 0xc43f1531U, 0x850e0e28U, 0x42984f67U, 0x03a9547eU, 0xc0fa7955U, 0x81cb624cU + /* 208 */ , 0x1fc53881U, 0x5ef42398U, 0x9da70eb3U, 0xdc9615aaU, 0x1b0054e5U, 0x5a314ffcU, 0x996262d7U, 0xd85379ceU + /* 216 */ , 0x174fe149U, 0x567efa50U, 0x952dd77bU, 0xd41ccc62U, 0x138a8d2dU, 0x52bb9634U, 0x91e8bb1fU, 0xd0d9a006U + /* 224 */ , 0xecf37e5eU, 0xadc26547U, 0x6e91486cU, 0x2fa05375U, 0xe836123aU, 0xa9070923U, 0x6a542408U, 0x2b653f11U + /* 232 */ , 0xe479a796U, 0xa548bc8fU, 0x661b91a4U, 0x272a8abdU, 0xe0bccbf2U, 0xa18dd0ebU, 0x62defdc0U, 0x23efe6d9U + /* 240 */ , 0xbde1bc14U, 0xfcd0a70dU, 0x3f838a26U, 0x7eb2913fU, 0xb924d070U, 0xf815cb69U, 0x3b46e642U, 0x7a77fd5bU + /* 248 */ , 0xb56b65dcU, 0xf45a7ec5U, 0x370953eeU, 0x763848f7U, 0xb1ae09b8U, 0xf09f12a1U, 0x33cc3f8aU, 0x72fd2493U + } + , + /* CRC32 table 6 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x376ac201U, 0x6ed48403U, 0x59be4602U, 0xdca80907U, 0xebc2cb06U, 0xb27c8d04U, 0x85164f05U + /* 8 */ , 0xb851130eU, 0x8f3bd10fU, 0xd685970dU, 0xe1ef550cU, 0x64f91a09U, 0x5393d808U, 0x0a2d9e0aU, 0x3d475c0bU + /* 16 */ , 0x70a3261cU, 0x47c9e41dU, 0x1e77a21fU, 0x291d601eU, 0xac0b2f1bU, 0x9b61ed1aU, 0xc2dfab18U, 0xf5b56919U + /* 24 */ , 0xc8f23512U, 0xff98f713U, 0xa626b111U, 0x914c7310U, 0x145a3c15U, 0x2330fe14U, 0x7a8eb816U, 0x4de47a17U + /* 32 */ , 0xe0464d38U, 0xd72c8f39U, 0x8e92c93bU, 0xb9f80b3aU, 0x3cee443fU, 0x0b84863eU, 0x523ac03cU, 0x6550023dU + /* 40 */ , 0x58175e36U, 0x6f7d9c37U, 0x36c3da35U, 0x01a91834U, 0x84bf5731U, 0xb3d59530U, 0xea6bd332U, 0xdd011133U + /* 48 */ , 0x90e56b24U, 0xa78fa925U, 0xfe31ef27U, 0xc95b2d26U, 0x4c4d6223U, 0x7b27a022U, 0x2299e620U, 0x15f32421U + /* 56 */ , 0x28b4782aU, 0x1fdeba2bU, 0x4660fc29U, 0x710a3e28U, 0xf41c712dU, 0xc376b32cU, 0x9ac8f52eU, 0xada2372fU + /* 64 */ , 0xc08d9a70U, 0xf7e75871U, 0xae591e73U, 0x9933dc72U, 0x1c259377U, 0x2b4f5176U, 0x72f11774U, 0x459bd575U + /* 72 */ , 0x78dc897eU, 0x4fb64b7fU, 0x16080d7dU, 0x2162cf7cU, 0xa4748079U, 0x931e4278U, 0xcaa0047aU, 0xfdcac67bU + /* 80 */ , 0xb02ebc6cU, 0x87447e6dU, 0xdefa386fU, 0xe990fa6eU, 0x6c86b56bU, 0x5bec776aU, 0x02523168U, 0x3538f369U + /* 88 */ , 0x087faf62U, 0x3f156d63U, 0x66ab2b61U, 0x51c1e960U, 0xd4d7a665U, 0xe3bd6464U, 0xba032266U, 0x8d69e067U + /* 96 */ , 0x20cbd748U, 0x17a11549U, 0x4e1f534bU, 0x7975914aU, 0xfc63de4fU, 0xcb091c4eU, 0x92b75a4cU, 0xa5dd984dU + /* 104 */ , 0x989ac446U, 0xaff00647U, 0xf64e4045U, 0xc1248244U, 0x4432cd41U, 0x73580f40U, 0x2ae64942U, 0x1d8c8b43U + /* 112 */ , 0x5068f154U, 0x67023355U, 0x3ebc7557U, 0x09d6b756U, 0x8cc0f853U, 0xbbaa3a52U, 0xe2147c50U, 0xd57ebe51U + /* 120 */ , 0xe839e25aU, 0xdf53205bU, 0x86ed6659U, 0xb187a458U, 0x3491eb5dU, 0x03fb295cU, 0x5a456f5eU, 0x6d2fad5fU + /* 128 */ , 0x801b35e1U, 0xb771f7e0U, 0xeecfb1e2U, 0xd9a573e3U, 0x5cb33ce6U, 0x6bd9fee7U, 0x3267b8e5U, 0x050d7ae4U + /* 136 */ , 0x384a26efU, 0x0f20e4eeU, 0x569ea2ecU, 0x61f460edU, 0xe4e22fe8U, 0xd388ede9U, 0x8a36abebU, 0xbd5c69eaU + /* 144 */ , 0xf0b813fdU, 0xc7d2d1fcU, 0x9e6c97feU, 0xa90655ffU, 0x2c101afaU, 0x1b7ad8fbU, 0x42c49ef9U, 0x75ae5cf8U + /* 152 */ , 0x48e900f3U, 0x7f83c2f2U, 0x263d84f0U, 0x115746f1U, 0x944109f4U, 0xa32bcbf5U, 0xfa958df7U, 0xcdff4ff6U + /* 160 */ , 0x605d78d9U, 0x5737bad8U, 0x0e89fcdaU, 0x39e33edbU, 0xbcf571deU, 0x8b9fb3dfU, 0xd221f5ddU, 0xe54b37dcU + /* 168 */ , 0xd80c6bd7U, 0xef66a9d6U, 0xb6d8efd4U, 0x81b22dd5U, 0x04a462d0U, 0x33cea0d1U, 0x6a70e6d3U, 0x5d1a24d2U + /* 176 */ , 0x10fe5ec5U, 0x27949cc4U, 0x7e2adac6U, 0x494018c7U, 0xcc5657c2U, 0xfb3c95c3U, 0xa282d3c1U, 0x95e811c0U + /* 184 */ , 0xa8af4dcbU, 0x9fc58fcaU, 0xc67bc9c8U, 0xf1110bc9U, 0x740744ccU, 0x436d86cdU, 0x1ad3c0cfU, 0x2db902ceU + /* 192 */ , 0x4096af91U, 0x77fc6d90U, 0x2e422b92U, 0x1928e993U, 0x9c3ea696U, 0xab546497U, 0xf2ea2295U, 0xc580e094U + /* 200 */ , 0xf8c7bc9fU, 0xcfad7e9eU, 0x9613389cU, 0xa179fa9dU, 0x246fb598U, 0x13057799U, 0x4abb319bU, 0x7dd1f39aU + /* 208 */ , 0x3035898dU, 0x075f4b8cU, 0x5ee10d8eU, 0x698bcf8fU, 0xec9d808aU, 0xdbf7428bU, 0x82490489U, 0xb523c688U + /* 216 */ , 0x88649a83U, 0xbf0e5882U, 0xe6b01e80U, 0xd1dadc81U, 0x54cc9384U, 0x63a65185U, 0x3a181787U, 0x0d72d586U + /* 224 */ , 0xa0d0e2a9U, 0x97ba20a8U, 0xce0466aaU, 0xf96ea4abU, 0x7c78ebaeU, 0x4b1229afU, 0x12ac6fadU, 0x25c6adacU + /* 232 */ , 0x1881f1a7U, 0x2feb33a6U, 0x765575a4U, 0x413fb7a5U, 0xc429f8a0U, 0xf3433aa1U, 0xaafd7ca3U, 0x9d97bea2U + /* 240 */ , 0xd073c4b5U, 0xe71906b4U, 0xbea740b6U, 0x89cd82b7U, 0x0cdbcdb2U, 0x3bb10fb3U, 0x620f49b1U, 0x55658bb0U + /* 248 */ , 0x6822d7bbU, 0x5f4815baU, 0x06f653b8U, 0x319c91b9U, 0xb48adebcU, 0x83e01cbdU, 0xda5e5abfU, 0xed3498beU + } + , + /* CRC32 table 7 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x6567bcb8U, 0x8bc809aaU, 0xeeafb512U, 0x5797628fU, 0x32f0de37U, 0xdc5f6b25U, 0xb938d79dU + /* 8 */ , 0xef28b4c5U, 0x8a4f087dU, 0x64e0bd6fU, 0x018701d7U, 0xb8bfd64aU, 0xddd86af2U, 0x3377dfe0U, 0x56106358U + /* 16 */ , 0x9f571950U, 0xfa30a5e8U, 0x149f10faU, 0x71f8ac42U, 0xc8c07bdfU, 0xada7c767U, 0x43087275U, 0x266fcecdU + /* 24 */ , 0x707fad95U, 0x1518112dU, 0xfbb7a43fU, 0x9ed01887U, 0x27e8cf1aU, 0x428f73a2U, 0xac20c6b0U, 0xc9477a08U + /* 32 */ , 0x3eaf32a0U, 0x5bc88e18U, 0xb5673b0aU, 0xd00087b2U, 0x6938502fU, 0x0c5fec97U, 0xe2f05985U, 0x8797e53dU + /* 40 */ , 0xd1878665U, 0xb4e03addU, 0x5a4f8fcfU, 0x3f283377U, 0x8610e4eaU, 0xe3775852U, 0x0dd8ed40U, 0x68bf51f8U + /* 48 */ , 0xa1f82bf0U, 0xc49f9748U, 0x2a30225aU, 0x4f579ee2U, 0xf66f497fU, 0x9308f5c7U, 0x7da740d5U, 0x18c0fc6dU + /* 56 */ , 0x4ed09f35U, 0x2bb7238dU, 0xc518969fU, 0xa07f2a27U, 0x1947fdbaU, 0x7c204102U, 0x928ff410U, 0xf7e848a8U + /* 64 */ , 0x3d58149bU, 0x583fa823U, 0xb6901d31U, 0xd3f7a189U, 0x6acf7614U, 0x0fa8caacU, 0xe1077fbeU, 0x8460c306U + /* 72 */ , 0xd270a05eU, 0xb7171ce6U, 0x59b8a9f4U, 0x3cdf154cU, 0x85e7c2d1U, 0xe0807e69U, 0x0e2fcb7bU, 0x6b4877c3U + /* 80 */ , 0xa20f0dcbU, 0xc768b173U, 0x29c70461U, 0x4ca0b8d9U, 0xf5986f44U, 0x90ffd3fcU, 0x7e5066eeU, 0x1b37da56U + /* 88 */ , 0x4d27b90eU, 0x284005b6U, 0xc6efb0a4U, 0xa3880c1cU, 0x1ab0db81U, 0x7fd76739U, 0x9178d22bU, 0xf41f6e93U + /* 96 */ , 0x03f7263bU, 0x66909a83U, 0x883f2f91U, 0xed589329U, 0x546044b4U, 0x3107f80cU, 0xdfa84d1eU, 0xbacff1a6U + /* 104 */ , 0xecdf92feU, 0x89b82e46U, 0x67179b54U, 0x027027ecU, 0xbb48f071U, 0xde2f4cc9U, 0x3080f9dbU, 0x55e74563U + /* 112 */ , 0x9ca03f6bU, 0xf9c783d3U, 0x176836c1U, 0x720f8a79U, 0xcb375de4U, 0xae50e15cU, 0x40ff544eU, 0x2598e8f6U + /* 120 */ , 0x73888baeU, 0x16ef3716U, 0xf8408204U, 0x9d273ebcU, 0x241fe921U, 0x41785599U, 0xafd7e08bU, 0xcab05c33U + /* 128 */ , 0x3bb659edU, 0x5ed1e555U, 0xb07e5047U, 0xd519ecffU, 0x6c213b62U, 0x094687daU, 0xe7e932c8U, 0x828e8e70U + /* 136 */ , 0xd49eed28U, 0xb1f95190U, 0x5f56e482U, 0x3a31583aU, 0x83098fa7U, 0xe66e331fU, 0x08c1860dU, 0x6da63ab5U + /* 144 */ , 0xa4e140bdU, 0xc186fc05U, 0x2f294917U, 0x4a4ef5afU, 0xf3762232U, 0x96119e8aU, 0x78be2b98U, 0x1dd99720U + /* 152 */ , 0x4bc9f478U, 0x2eae48c0U, 0xc001fdd2U, 0xa566416aU, 0x1c5e96f7U, 0x79392a4fU, 0x97969f5dU, 0xf2f123e5U + /* 160 */ , 0x05196b4dU, 0x607ed7f5U, 0x8ed162e7U, 0xebb6de5fU, 0x528e09c2U, 0x37e9b57aU, 0xd9460068U, 0xbc21bcd0U + /* 168 */ , 0xea31df88U, 0x8f566330U, 0x61f9d622U, 0x049e6a9aU, 0xbda6bd07U, 0xd8c101bfU, 0x366eb4adU, 0x53090815U + /* 176 */ , 0x9a4e721dU, 0xff29cea5U, 0x11867bb7U, 0x74e1c70fU, 0xcdd91092U, 0xa8beac2aU, 0x46111938U, 0x2376a580U + /* 184 */ , 0x7566c6d8U, 0x10017a60U, 0xfeaecf72U, 0x9bc973caU, 0x22f1a457U, 0x479618efU, 0xa939adfdU, 0xcc5e1145U + /* 192 */ , 0x06ee4d76U, 0x6389f1ceU, 0x8d2644dcU, 0xe841f864U, 0x51792ff9U, 0x341e9341U, 0xdab12653U, 0xbfd69aebU + /* 200 */ , 0xe9c6f9b3U, 0x8ca1450bU, 0x620ef019U, 0x07694ca1U, 0xbe519b3cU, 0xdb362784U, 0x35999296U, 0x50fe2e2eU + /* 208 */ , 0x99b95426U, 0xfcdee89eU, 0x12715d8cU, 0x7716e134U, 0xce2e36a9U, 0xab498a11U, 0x45e63f03U, 0x208183bbU + /* 216 */ , 0x7691e0e3U, 0x13f65c5bU, 0xfd59e949U, 0x983e55f1U, 0x2106826cU, 0x44613ed4U, 0xaace8bc6U, 0xcfa9377eU + /* 224 */ , 0x38417fd6U, 0x5d26c36eU, 0xb389767cU, 0xd6eecac4U, 0x6fd61d59U, 0x0ab1a1e1U, 0xe41e14f3U, 0x8179a84bU + /* 232 */ , 0xd769cb13U, 0xb20e77abU, 0x5ca1c2b9U, 0x39c67e01U, 0x80fea99cU, 0xe5991524U, 0x0b36a036U, 0x6e511c8eU + /* 240 */ , 0xa7166686U, 0xc271da3eU, 0x2cde6f2cU, 0x49b9d394U, 0xf0810409U, 0x95e6b8b1U, 0x7b490da3U, 0x1e2eb11bU + /* 248 */ , 0x483ed243U, 0x2d596efbU, 0xc3f6dbe9U, 0xa6916751U, 0x1fa9b0ccU, 0x7ace0c74U, 0x9461b966U, 0xf10605deU + } + #endif + }; + +juint StubRoutines::zarch::_crc32c_table[CRC32_TABLES][CRC32_COLUMN_SIZE] = { + /* polyBits = 4394350321 0x0000000105ec76f1L, shifted = 0x82f63b78 */ + /* CRC32C table for single bytes, auto-generated. DO NOT MODIFY! */ + /* CRC32C table 0 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xf26b8303U, 0xe13b70f7U, 0x1350f3f4U, 0xc79a971fU, 0x35f1141cU, 0x26a1e7e8U, 0xd4ca64ebU + /* 8 */ , 0x8ad958cfU, 0x78b2dbccU, 0x6be22838U, 0x9989ab3bU, 0x4d43cfd0U, 0xbf284cd3U, 0xac78bf27U, 0x5e133c24U + /* 16 */ , 0x105ec76fU, 0xe235446cU, 0xf165b798U, 0x030e349bU, 0xd7c45070U, 0x25afd373U, 0x36ff2087U, 0xc494a384U + /* 24 */ , 0x9a879fa0U, 0x68ec1ca3U, 0x7bbcef57U, 0x89d76c54U, 0x5d1d08bfU, 0xaf768bbcU, 0xbc267848U, 0x4e4dfb4bU + /* 32 */ , 0x20bd8edeU, 0xd2d60dddU, 0xc186fe29U, 0x33ed7d2aU, 0xe72719c1U, 0x154c9ac2U, 0x061c6936U, 0xf477ea35U + /* 40 */ , 0xaa64d611U, 0x580f5512U, 0x4b5fa6e6U, 0xb93425e5U, 0x6dfe410eU, 0x9f95c20dU, 0x8cc531f9U, 0x7eaeb2faU + /* 48 */ , 0x30e349b1U, 0xc288cab2U, 0xd1d83946U, 0x23b3ba45U, 0xf779deaeU, 0x05125dadU, 0x1642ae59U, 0xe4292d5aU + /* 56 */ , 0xba3a117eU, 0x4851927dU, 0x5b016189U, 0xa96ae28aU, 0x7da08661U, 0x8fcb0562U, 0x9c9bf696U, 0x6ef07595U + /* 64 */ , 0x417b1dbcU, 0xb3109ebfU, 0xa0406d4bU, 0x522bee48U, 0x86e18aa3U, 0x748a09a0U, 0x67dafa54U, 0x95b17957U + /* 72 */ , 0xcba24573U, 0x39c9c670U, 0x2a993584U, 0xd8f2b687U, 0x0c38d26cU, 0xfe53516fU, 0xed03a29bU, 0x1f682198U + /* 80 */ , 0x5125dad3U, 0xa34e59d0U, 0xb01eaa24U, 0x42752927U, 0x96bf4dccU, 0x64d4cecfU, 0x77843d3bU, 0x85efbe38U + /* 88 */ , 0xdbfc821cU, 0x2997011fU, 0x3ac7f2ebU, 0xc8ac71e8U, 0x1c661503U, 0xee0d9600U, 0xfd5d65f4U, 0x0f36e6f7U + /* 96 */ , 0x61c69362U, 0x93ad1061U, 0x80fde395U, 0x72966096U, 0xa65c047dU, 0x5437877eU, 0x4767748aU, 0xb50cf789U + /* 104 */ , 0xeb1fcbadU, 0x197448aeU, 0x0a24bb5aU, 0xf84f3859U, 0x2c855cb2U, 0xdeeedfb1U, 0xcdbe2c45U, 0x3fd5af46U + /* 112 */ , 0x7198540dU, 0x83f3d70eU, 0x90a324faU, 0x62c8a7f9U, 0xb602c312U, 0x44694011U, 0x5739b3e5U, 0xa55230e6U + /* 120 */ , 0xfb410cc2U, 0x092a8fc1U, 0x1a7a7c35U, 0xe811ff36U, 0x3cdb9bddU, 0xceb018deU, 0xdde0eb2aU, 0x2f8b6829U + /* 128 */ , 0x82f63b78U, 0x709db87bU, 0x63cd4b8fU, 0x91a6c88cU, 0x456cac67U, 0xb7072f64U, 0xa457dc90U, 0x563c5f93U + /* 136 */ , 0x082f63b7U, 0xfa44e0b4U, 0xe9141340U, 0x1b7f9043U, 0xcfb5f4a8U, 0x3dde77abU, 0x2e8e845fU, 0xdce5075cU + /* 144 */ , 0x92a8fc17U, 0x60c37f14U, 0x73938ce0U, 0x81f80fe3U, 0x55326b08U, 0xa759e80bU, 0xb4091bffU, 0x466298fcU + /* 152 */ , 0x1871a4d8U, 0xea1a27dbU, 0xf94ad42fU, 0x0b21572cU, 0xdfeb33c7U, 0x2d80b0c4U, 0x3ed04330U, 0xccbbc033U + /* 160 */ , 0xa24bb5a6U, 0x502036a5U, 0x4370c551U, 0xb11b4652U, 0x65d122b9U, 0x97baa1baU, 0x84ea524eU, 0x7681d14dU + /* 168 */ , 0x2892ed69U, 0xdaf96e6aU, 0xc9a99d9eU, 0x3bc21e9dU, 0xef087a76U, 0x1d63f975U, 0x0e330a81U, 0xfc588982U + /* 176 */ , 0xb21572c9U, 0x407ef1caU, 0x532e023eU, 0xa145813dU, 0x758fe5d6U, 0x87e466d5U, 0x94b49521U, 0x66df1622U + /* 184 */ , 0x38cc2a06U, 0xcaa7a905U, 0xd9f75af1U, 0x2b9cd9f2U, 0xff56bd19U, 0x0d3d3e1aU, 0x1e6dcdeeU, 0xec064eedU + /* 192 */ , 0xc38d26c4U, 0x31e6a5c7U, 0x22b65633U, 0xd0ddd530U, 0x0417b1dbU, 0xf67c32d8U, 0xe52cc12cU, 0x1747422fU + /* 200 */ , 0x49547e0bU, 0xbb3ffd08U, 0xa86f0efcU, 0x5a048dffU, 0x8ecee914U, 0x7ca56a17U, 0x6ff599e3U, 0x9d9e1ae0U + /* 208 */ , 0xd3d3e1abU, 0x21b862a8U, 0x32e8915cU, 0xc083125fU, 0x144976b4U, 0xe622f5b7U, 0xf5720643U, 0x07198540U + /* 216 */ , 0x590ab964U, 0xab613a67U, 0xb831c993U, 0x4a5a4a90U, 0x9e902e7bU, 0x6cfbad78U, 0x7fab5e8cU, 0x8dc0dd8fU + /* 224 */ , 0xe330a81aU, 0x115b2b19U, 0x020bd8edU, 0xf0605beeU, 0x24aa3f05U, 0xd6c1bc06U, 0xc5914ff2U, 0x37faccf1U + /* 232 */ , 0x69e9f0d5U, 0x9b8273d6U, 0x88d28022U, 0x7ab90321U, 0xae7367caU, 0x5c18e4c9U, 0x4f48173dU, 0xbd23943eU + /* 240 */ , 0xf36e6f75U, 0x0105ec76U, 0x12551f82U, 0xe03e9c81U, 0x34f4f86aU, 0xc69f7b69U, 0xd5cf889dU, 0x27a40b9eU + /* 248 */ , 0x79b737baU, 0x8bdcb4b9U, 0x988c474dU, 0x6ae7c44eU, 0xbe2da0a5U, 0x4c4623a6U, 0x5f16d052U, 0xad7d5351U + } + #ifdef CRC32_BYFOUR + , + /* CRC32C table 1 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x13a29877U, 0x274530eeU, 0x34e7a899U, 0x4e8a61dcU, 0x5d28f9abU, 0x69cf5132U, 0x7a6dc945U + /* 8 */ , 0x9d14c3b8U, 0x8eb65bcfU, 0xba51f356U, 0xa9f36b21U, 0xd39ea264U, 0xc03c3a13U, 0xf4db928aU, 0xe7790afdU + /* 16 */ , 0x3fc5f181U, 0x2c6769f6U, 0x1880c16fU, 0x0b225918U, 0x714f905dU, 0x62ed082aU, 0x560aa0b3U, 0x45a838c4U + /* 24 */ , 0xa2d13239U, 0xb173aa4eU, 0x859402d7U, 0x96369aa0U, 0xec5b53e5U, 0xfff9cb92U, 0xcb1e630bU, 0xd8bcfb7cU + /* 32 */ , 0x7f8be302U, 0x6c297b75U, 0x58ced3ecU, 0x4b6c4b9bU, 0x310182deU, 0x22a31aa9U, 0x1644b230U, 0x05e62a47U + /* 40 */ , 0xe29f20baU, 0xf13db8cdU, 0xc5da1054U, 0xd6788823U, 0xac154166U, 0xbfb7d911U, 0x8b507188U, 0x98f2e9ffU + /* 48 */ , 0x404e1283U, 0x53ec8af4U, 0x670b226dU, 0x74a9ba1aU, 0x0ec4735fU, 0x1d66eb28U, 0x298143b1U, 0x3a23dbc6U + /* 56 */ , 0xdd5ad13bU, 0xcef8494cU, 0xfa1fe1d5U, 0xe9bd79a2U, 0x93d0b0e7U, 0x80722890U, 0xb4958009U, 0xa737187eU + /* 64 */ , 0xff17c604U, 0xecb55e73U, 0xd852f6eaU, 0xcbf06e9dU, 0xb19da7d8U, 0xa23f3fafU, 0x96d89736U, 0x857a0f41U + /* 72 */ , 0x620305bcU, 0x71a19dcbU, 0x45463552U, 0x56e4ad25U, 0x2c896460U, 0x3f2bfc17U, 0x0bcc548eU, 0x186eccf9U + /* 80 */ , 0xc0d23785U, 0xd370aff2U, 0xe797076bU, 0xf4359f1cU, 0x8e585659U, 0x9dface2eU, 0xa91d66b7U, 0xbabffec0U + /* 88 */ , 0x5dc6f43dU, 0x4e646c4aU, 0x7a83c4d3U, 0x69215ca4U, 0x134c95e1U, 0x00ee0d96U, 0x3409a50fU, 0x27ab3d78U + /* 96 */ , 0x809c2506U, 0x933ebd71U, 0xa7d915e8U, 0xb47b8d9fU, 0xce1644daU, 0xddb4dcadU, 0xe9537434U, 0xfaf1ec43U + /* 104 */ , 0x1d88e6beU, 0x0e2a7ec9U, 0x3acdd650U, 0x296f4e27U, 0x53028762U, 0x40a01f15U, 0x7447b78cU, 0x67e52ffbU + /* 112 */ , 0xbf59d487U, 0xacfb4cf0U, 0x981ce469U, 0x8bbe7c1eU, 0xf1d3b55bU, 0xe2712d2cU, 0xd69685b5U, 0xc5341dc2U + /* 120 */ , 0x224d173fU, 0x31ef8f48U, 0x050827d1U, 0x16aabfa6U, 0x6cc776e3U, 0x7f65ee94U, 0x4b82460dU, 0x5820de7aU + /* 128 */ , 0xfbc3faf9U, 0xe861628eU, 0xdc86ca17U, 0xcf245260U, 0xb5499b25U, 0xa6eb0352U, 0x920cabcbU, 0x81ae33bcU + /* 136 */ , 0x66d73941U, 0x7575a136U, 0x419209afU, 0x523091d8U, 0x285d589dU, 0x3bffc0eaU, 0x0f186873U, 0x1cbaf004U + /* 144 */ , 0xc4060b78U, 0xd7a4930fU, 0xe3433b96U, 0xf0e1a3e1U, 0x8a8c6aa4U, 0x992ef2d3U, 0xadc95a4aU, 0xbe6bc23dU + /* 152 */ , 0x5912c8c0U, 0x4ab050b7U, 0x7e57f82eU, 0x6df56059U, 0x1798a91cU, 0x043a316bU, 0x30dd99f2U, 0x237f0185U + /* 160 */ , 0x844819fbU, 0x97ea818cU, 0xa30d2915U, 0xb0afb162U, 0xcac27827U, 0xd960e050U, 0xed8748c9U, 0xfe25d0beU + /* 168 */ , 0x195cda43U, 0x0afe4234U, 0x3e19eaadU, 0x2dbb72daU, 0x57d6bb9fU, 0x447423e8U, 0x70938b71U, 0x63311306U + /* 176 */ , 0xbb8de87aU, 0xa82f700dU, 0x9cc8d894U, 0x8f6a40e3U, 0xf50789a6U, 0xe6a511d1U, 0xd242b948U, 0xc1e0213fU + /* 184 */ , 0x26992bc2U, 0x353bb3b5U, 0x01dc1b2cU, 0x127e835bU, 0x68134a1eU, 0x7bb1d269U, 0x4f567af0U, 0x5cf4e287U + /* 192 */ , 0x04d43cfdU, 0x1776a48aU, 0x23910c13U, 0x30339464U, 0x4a5e5d21U, 0x59fcc556U, 0x6d1b6dcfU, 0x7eb9f5b8U + /* 200 */ , 0x99c0ff45U, 0x8a626732U, 0xbe85cfabU, 0xad2757dcU, 0xd74a9e99U, 0xc4e806eeU, 0xf00fae77U, 0xe3ad3600U + /* 208 */ , 0x3b11cd7cU, 0x28b3550bU, 0x1c54fd92U, 0x0ff665e5U, 0x759baca0U, 0x663934d7U, 0x52de9c4eU, 0x417c0439U + /* 216 */ , 0xa6050ec4U, 0xb5a796b3U, 0x81403e2aU, 0x92e2a65dU, 0xe88f6f18U, 0xfb2df76fU, 0xcfca5ff6U, 0xdc68c781U + /* 224 */ , 0x7b5fdfffU, 0x68fd4788U, 0x5c1aef11U, 0x4fb87766U, 0x35d5be23U, 0x26772654U, 0x12908ecdU, 0x013216baU + /* 232 */ , 0xe64b1c47U, 0xf5e98430U, 0xc10e2ca9U, 0xd2acb4deU, 0xa8c17d9bU, 0xbb63e5ecU, 0x8f844d75U, 0x9c26d502U + /* 240 */ , 0x449a2e7eU, 0x5738b609U, 0x63df1e90U, 0x707d86e7U, 0x0a104fa2U, 0x19b2d7d5U, 0x2d557f4cU, 0x3ef7e73bU + /* 248 */ , 0xd98eedc6U, 0xca2c75b1U, 0xfecbdd28U, 0xed69455fU, 0x97048c1aU, 0x84a6146dU, 0xb041bcf4U, 0xa3e32483U + } + , + /* CRC32C table 2 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xa541927eU, 0x4f6f520dU, 0xea2ec073U, 0x9edea41aU, 0x3b9f3664U, 0xd1b1f617U, 0x74f06469U + /* 8 */ , 0x38513ec5U, 0x9d10acbbU, 0x773e6cc8U, 0xd27ffeb6U, 0xa68f9adfU, 0x03ce08a1U, 0xe9e0c8d2U, 0x4ca15aacU + /* 16 */ , 0x70a27d8aU, 0xd5e3eff4U, 0x3fcd2f87U, 0x9a8cbdf9U, 0xee7cd990U, 0x4b3d4beeU, 0xa1138b9dU, 0x045219e3U + /* 24 */ , 0x48f3434fU, 0xedb2d131U, 0x079c1142U, 0xa2dd833cU, 0xd62de755U, 0x736c752bU, 0x9942b558U, 0x3c032726U + /* 32 */ , 0xe144fb14U, 0x4405696aU, 0xae2ba919U, 0x0b6a3b67U, 0x7f9a5f0eU, 0xdadbcd70U, 0x30f50d03U, 0x95b49f7dU + /* 40 */ , 0xd915c5d1U, 0x7c5457afU, 0x967a97dcU, 0x333b05a2U, 0x47cb61cbU, 0xe28af3b5U, 0x08a433c6U, 0xade5a1b8U + /* 48 */ , 0x91e6869eU, 0x34a714e0U, 0xde89d493U, 0x7bc846edU, 0x0f382284U, 0xaa79b0faU, 0x40577089U, 0xe516e2f7U + /* 56 */ , 0xa9b7b85bU, 0x0cf62a25U, 0xe6d8ea56U, 0x43997828U, 0x37691c41U, 0x92288e3fU, 0x78064e4cU, 0xdd47dc32U + /* 64 */ , 0xc76580d9U, 0x622412a7U, 0x880ad2d4U, 0x2d4b40aaU, 0x59bb24c3U, 0xfcfab6bdU, 0x16d476ceU, 0xb395e4b0U + /* 72 */ , 0xff34be1cU, 0x5a752c62U, 0xb05bec11U, 0x151a7e6fU, 0x61ea1a06U, 0xc4ab8878U, 0x2e85480bU, 0x8bc4da75U + /* 80 */ , 0xb7c7fd53U, 0x12866f2dU, 0xf8a8af5eU, 0x5de93d20U, 0x29195949U, 0x8c58cb37U, 0x66760b44U, 0xc337993aU + /* 88 */ , 0x8f96c396U, 0x2ad751e8U, 0xc0f9919bU, 0x65b803e5U, 0x1148678cU, 0xb409f5f2U, 0x5e273581U, 0xfb66a7ffU + /* 96 */ , 0x26217bcdU, 0x8360e9b3U, 0x694e29c0U, 0xcc0fbbbeU, 0xb8ffdfd7U, 0x1dbe4da9U, 0xf7908ddaU, 0x52d11fa4U + /* 104 */ , 0x1e704508U, 0xbb31d776U, 0x511f1705U, 0xf45e857bU, 0x80aee112U, 0x25ef736cU, 0xcfc1b31fU, 0x6a802161U + /* 112 */ , 0x56830647U, 0xf3c29439U, 0x19ec544aU, 0xbcadc634U, 0xc85da25dU, 0x6d1c3023U, 0x8732f050U, 0x2273622eU + /* 120 */ , 0x6ed23882U, 0xcb93aafcU, 0x21bd6a8fU, 0x84fcf8f1U, 0xf00c9c98U, 0x554d0ee6U, 0xbf63ce95U, 0x1a225cebU + /* 128 */ , 0x8b277743U, 0x2e66e53dU, 0xc448254eU, 0x6109b730U, 0x15f9d359U, 0xb0b84127U, 0x5a968154U, 0xffd7132aU + /* 136 */ , 0xb3764986U, 0x1637dbf8U, 0xfc191b8bU, 0x595889f5U, 0x2da8ed9cU, 0x88e97fe2U, 0x62c7bf91U, 0xc7862defU + /* 144 */ , 0xfb850ac9U, 0x5ec498b7U, 0xb4ea58c4U, 0x11abcabaU, 0x655baed3U, 0xc01a3cadU, 0x2a34fcdeU, 0x8f756ea0U + /* 152 */ , 0xc3d4340cU, 0x6695a672U, 0x8cbb6601U, 0x29faf47fU, 0x5d0a9016U, 0xf84b0268U, 0x1265c21bU, 0xb7245065U + /* 160 */ , 0x6a638c57U, 0xcf221e29U, 0x250cde5aU, 0x804d4c24U, 0xf4bd284dU, 0x51fcba33U, 0xbbd27a40U, 0x1e93e83eU + /* 168 */ , 0x5232b292U, 0xf77320ecU, 0x1d5de09fU, 0xb81c72e1U, 0xccec1688U, 0x69ad84f6U, 0x83834485U, 0x26c2d6fbU + /* 176 */ , 0x1ac1f1ddU, 0xbf8063a3U, 0x55aea3d0U, 0xf0ef31aeU, 0x841f55c7U, 0x215ec7b9U, 0xcb7007caU, 0x6e3195b4U + /* 184 */ , 0x2290cf18U, 0x87d15d66U, 0x6dff9d15U, 0xc8be0f6bU, 0xbc4e6b02U, 0x190ff97cU, 0xf321390fU, 0x5660ab71U + /* 192 */ , 0x4c42f79aU, 0xe90365e4U, 0x032da597U, 0xa66c37e9U, 0xd29c5380U, 0x77ddc1feU, 0x9df3018dU, 0x38b293f3U + /* 200 */ , 0x7413c95fU, 0xd1525b21U, 0x3b7c9b52U, 0x9e3d092cU, 0xeacd6d45U, 0x4f8cff3bU, 0xa5a23f48U, 0x00e3ad36U + /* 208 */ , 0x3ce08a10U, 0x99a1186eU, 0x738fd81dU, 0xd6ce4a63U, 0xa23e2e0aU, 0x077fbc74U, 0xed517c07U, 0x4810ee79U + /* 216 */ , 0x04b1b4d5U, 0xa1f026abU, 0x4bdee6d8U, 0xee9f74a6U, 0x9a6f10cfU, 0x3f2e82b1U, 0xd50042c2U, 0x7041d0bcU + /* 224 */ , 0xad060c8eU, 0x08479ef0U, 0xe2695e83U, 0x4728ccfdU, 0x33d8a894U, 0x96993aeaU, 0x7cb7fa99U, 0xd9f668e7U + /* 232 */ , 0x9557324bU, 0x3016a035U, 0xda386046U, 0x7f79f238U, 0x0b899651U, 0xaec8042fU, 0x44e6c45cU, 0xe1a75622U + /* 240 */ , 0xdda47104U, 0x78e5e37aU, 0x92cb2309U, 0x378ab177U, 0x437ad51eU, 0xe63b4760U, 0x0c158713U, 0xa954156dU + /* 248 */ , 0xe5f54fc1U, 0x40b4ddbfU, 0xaa9a1dccU, 0x0fdb8fb2U, 0x7b2bebdbU, 0xde6a79a5U, 0x3444b9d6U, 0x91052ba8U + } + , + /* CRC32C table 3 for quad-bytes (little-endian), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xdd45aab8U, 0xbf672381U, 0x62228939U, 0x7b2231f3U, 0xa6679b4bU, 0xc4451272U, 0x1900b8caU + /* 8 */ , 0xf64463e6U, 0x2b01c95eU, 0x49234067U, 0x9466eadfU, 0x8d665215U, 0x5023f8adU, 0x32017194U, 0xef44db2cU + /* 16 */ , 0xe964b13dU, 0x34211b85U, 0x560392bcU, 0x8b463804U, 0x924680ceU, 0x4f032a76U, 0x2d21a34fU, 0xf06409f7U + /* 24 */ , 0x1f20d2dbU, 0xc2657863U, 0xa047f15aU, 0x7d025be2U, 0x6402e328U, 0xb9474990U, 0xdb65c0a9U, 0x06206a11U + /* 32 */ , 0xd725148bU, 0x0a60be33U, 0x6842370aU, 0xb5079db2U, 0xac072578U, 0x71428fc0U, 0x136006f9U, 0xce25ac41U + /* 40 */ , 0x2161776dU, 0xfc24ddd5U, 0x9e0654ecU, 0x4343fe54U, 0x5a43469eU, 0x8706ec26U, 0xe524651fU, 0x3861cfa7U + /* 48 */ , 0x3e41a5b6U, 0xe3040f0eU, 0x81268637U, 0x5c632c8fU, 0x45639445U, 0x98263efdU, 0xfa04b7c4U, 0x27411d7cU + /* 56 */ , 0xc805c650U, 0x15406ce8U, 0x7762e5d1U, 0xaa274f69U, 0xb327f7a3U, 0x6e625d1bU, 0x0c40d422U, 0xd1057e9aU + /* 64 */ , 0xaba65fe7U, 0x76e3f55fU, 0x14c17c66U, 0xc984d6deU, 0xd0846e14U, 0x0dc1c4acU, 0x6fe34d95U, 0xb2a6e72dU + /* 72 */ , 0x5de23c01U, 0x80a796b9U, 0xe2851f80U, 0x3fc0b538U, 0x26c00df2U, 0xfb85a74aU, 0x99a72e73U, 0x44e284cbU + /* 80 */ , 0x42c2eedaU, 0x9f874462U, 0xfda5cd5bU, 0x20e067e3U, 0x39e0df29U, 0xe4a57591U, 0x8687fca8U, 0x5bc25610U + /* 88 */ , 0xb4868d3cU, 0x69c32784U, 0x0be1aebdU, 0xd6a40405U, 0xcfa4bccfU, 0x12e11677U, 0x70c39f4eU, 0xad8635f6U + /* 96 */ , 0x7c834b6cU, 0xa1c6e1d4U, 0xc3e468edU, 0x1ea1c255U, 0x07a17a9fU, 0xdae4d027U, 0xb8c6591eU, 0x6583f3a6U + /* 104 */ , 0x8ac7288aU, 0x57828232U, 0x35a00b0bU, 0xe8e5a1b3U, 0xf1e51979U, 0x2ca0b3c1U, 0x4e823af8U, 0x93c79040U + /* 112 */ , 0x95e7fa51U, 0x48a250e9U, 0x2a80d9d0U, 0xf7c57368U, 0xeec5cba2U, 0x3380611aU, 0x51a2e823U, 0x8ce7429bU + /* 120 */ , 0x63a399b7U, 0xbee6330fU, 0xdcc4ba36U, 0x0181108eU, 0x1881a844U, 0xc5c402fcU, 0xa7e68bc5U, 0x7aa3217dU + /* 128 */ , 0x52a0c93fU, 0x8fe56387U, 0xedc7eabeU, 0x30824006U, 0x2982f8ccU, 0xf4c75274U, 0x96e5db4dU, 0x4ba071f5U + /* 136 */ , 0xa4e4aad9U, 0x79a10061U, 0x1b838958U, 0xc6c623e0U, 0xdfc69b2aU, 0x02833192U, 0x60a1b8abU, 0xbde41213U + /* 144 */ , 0xbbc47802U, 0x6681d2baU, 0x04a35b83U, 0xd9e6f13bU, 0xc0e649f1U, 0x1da3e349U, 0x7f816a70U, 0xa2c4c0c8U + /* 152 */ , 0x4d801be4U, 0x90c5b15cU, 0xf2e73865U, 0x2fa292ddU, 0x36a22a17U, 0xebe780afU, 0x89c50996U, 0x5480a32eU + /* 160 */ , 0x8585ddb4U, 0x58c0770cU, 0x3ae2fe35U, 0xe7a7548dU, 0xfea7ec47U, 0x23e246ffU, 0x41c0cfc6U, 0x9c85657eU + /* 168 */ , 0x73c1be52U, 0xae8414eaU, 0xcca69dd3U, 0x11e3376bU, 0x08e38fa1U, 0xd5a62519U, 0xb784ac20U, 0x6ac10698U + /* 176 */ , 0x6ce16c89U, 0xb1a4c631U, 0xd3864f08U, 0x0ec3e5b0U, 0x17c35d7aU, 0xca86f7c2U, 0xa8a47efbU, 0x75e1d443U + /* 184 */ , 0x9aa50f6fU, 0x47e0a5d7U, 0x25c22ceeU, 0xf8878656U, 0xe1873e9cU, 0x3cc29424U, 0x5ee01d1dU, 0x83a5b7a5U + /* 192 */ , 0xf90696d8U, 0x24433c60U, 0x4661b559U, 0x9b241fe1U, 0x8224a72bU, 0x5f610d93U, 0x3d4384aaU, 0xe0062e12U + /* 200 */ , 0x0f42f53eU, 0xd2075f86U, 0xb025d6bfU, 0x6d607c07U, 0x7460c4cdU, 0xa9256e75U, 0xcb07e74cU, 0x16424df4U + /* 208 */ , 0x106227e5U, 0xcd278d5dU, 0xaf050464U, 0x7240aedcU, 0x6b401616U, 0xb605bcaeU, 0xd4273597U, 0x09629f2fU + /* 216 */ , 0xe6264403U, 0x3b63eebbU, 0x59416782U, 0x8404cd3aU, 0x9d0475f0U, 0x4041df48U, 0x22635671U, 0xff26fcc9U + /* 224 */ , 0x2e238253U, 0xf36628ebU, 0x9144a1d2U, 0x4c010b6aU, 0x5501b3a0U, 0x88441918U, 0xea669021U, 0x37233a99U + /* 232 */ , 0xd867e1b5U, 0x05224b0dU, 0x6700c234U, 0xba45688cU, 0xa345d046U, 0x7e007afeU, 0x1c22f3c7U, 0xc167597fU + /* 240 */ , 0xc747336eU, 0x1a0299d6U, 0x782010efU, 0xa565ba57U, 0xbc65029dU, 0x6120a825U, 0x0302211cU, 0xde478ba4U + /* 248 */ , 0x31035088U, 0xec46fa30U, 0x8e647309U, 0x5321d9b1U, 0x4a21617bU, 0x9764cbc3U, 0xf54642faU, 0x2803e842U + } + , + /* CRC32C table 4 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x03836bf2U, 0xf7703be1U, 0xf4f35013U, 0x1f979ac7U, 0x1c14f135U, 0xe8e7a126U, 0xeb64cad4U + /* 8 */ , 0xcf58d98aU, 0xccdbb278U, 0x3828e26bU, 0x3bab8999U, 0xd0cf434dU, 0xd34c28bfU, 0x27bf78acU, 0x243c135eU + /* 16 */ , 0x6fc75e10U, 0x6c4435e2U, 0x98b765f1U, 0x9b340e03U, 0x7050c4d7U, 0x73d3af25U, 0x8720ff36U, 0x84a394c4U + /* 24 */ , 0xa09f879aU, 0xa31cec68U, 0x57efbc7bU, 0x546cd789U, 0xbf081d5dU, 0xbc8b76afU, 0x487826bcU, 0x4bfb4d4eU + /* 32 */ , 0xde8ebd20U, 0xdd0dd6d2U, 0x29fe86c1U, 0x2a7ded33U, 0xc11927e7U, 0xc29a4c15U, 0x36691c06U, 0x35ea77f4U + /* 40 */ , 0x11d664aaU, 0x12550f58U, 0xe6a65f4bU, 0xe52534b9U, 0x0e41fe6dU, 0x0dc2959fU, 0xf931c58cU, 0xfab2ae7eU + /* 48 */ , 0xb149e330U, 0xb2ca88c2U, 0x4639d8d1U, 0x45bab323U, 0xaede79f7U, 0xad5d1205U, 0x59ae4216U, 0x5a2d29e4U + /* 56 */ , 0x7e113abaU, 0x7d925148U, 0x8961015bU, 0x8ae26aa9U, 0x6186a07dU, 0x6205cb8fU, 0x96f69b9cU, 0x9575f06eU + /* 64 */ , 0xbc1d7b41U, 0xbf9e10b3U, 0x4b6d40a0U, 0x48ee2b52U, 0xa38ae186U, 0xa0098a74U, 0x54fada67U, 0x5779b195U + /* 72 */ , 0x7345a2cbU, 0x70c6c939U, 0x8435992aU, 0x87b6f2d8U, 0x6cd2380cU, 0x6f5153feU, 0x9ba203edU, 0x9821681fU + /* 80 */ , 0xd3da2551U, 0xd0594ea3U, 0x24aa1eb0U, 0x27297542U, 0xcc4dbf96U, 0xcfced464U, 0x3b3d8477U, 0x38beef85U + /* 88 */ , 0x1c82fcdbU, 0x1f019729U, 0xebf2c73aU, 0xe871acc8U, 0x0315661cU, 0x00960deeU, 0xf4655dfdU, 0xf7e6360fU + /* 96 */ , 0x6293c661U, 0x6110ad93U, 0x95e3fd80U, 0x96609672U, 0x7d045ca6U, 0x7e873754U, 0x8a746747U, 0x89f70cb5U + /* 104 */ , 0xadcb1febU, 0xae487419U, 0x5abb240aU, 0x59384ff8U, 0xb25c852cU, 0xb1dfeedeU, 0x452cbecdU, 0x46afd53fU + /* 112 */ , 0x0d549871U, 0x0ed7f383U, 0xfa24a390U, 0xf9a7c862U, 0x12c302b6U, 0x11406944U, 0xe5b33957U, 0xe63052a5U + /* 120 */ , 0xc20c41fbU, 0xc18f2a09U, 0x357c7a1aU, 0x36ff11e8U, 0xdd9bdb3cU, 0xde18b0ceU, 0x2aebe0ddU, 0x29688b2fU + /* 128 */ , 0x783bf682U, 0x7bb89d70U, 0x8f4bcd63U, 0x8cc8a691U, 0x67ac6c45U, 0x642f07b7U, 0x90dc57a4U, 0x935f3c56U + /* 136 */ , 0xb7632f08U, 0xb4e044faU, 0x401314e9U, 0x43907f1bU, 0xa8f4b5cfU, 0xab77de3dU, 0x5f848e2eU, 0x5c07e5dcU + /* 144 */ , 0x17fca892U, 0x147fc360U, 0xe08c9373U, 0xe30ff881U, 0x086b3255U, 0x0be859a7U, 0xff1b09b4U, 0xfc986246U + /* 152 */ , 0xd8a47118U, 0xdb271aeaU, 0x2fd44af9U, 0x2c57210bU, 0xc733ebdfU, 0xc4b0802dU, 0x3043d03eU, 0x33c0bbccU + /* 160 */ , 0xa6b54ba2U, 0xa5362050U, 0x51c57043U, 0x52461bb1U, 0xb922d165U, 0xbaa1ba97U, 0x4e52ea84U, 0x4dd18176U + /* 168 */ , 0x69ed9228U, 0x6a6ef9daU, 0x9e9da9c9U, 0x9d1ec23bU, 0x767a08efU, 0x75f9631dU, 0x810a330eU, 0x828958fcU + /* 176 */ , 0xc97215b2U, 0xcaf17e40U, 0x3e022e53U, 0x3d8145a1U, 0xd6e58f75U, 0xd566e487U, 0x2195b494U, 0x2216df66U + /* 184 */ , 0x062acc38U, 0x05a9a7caU, 0xf15af7d9U, 0xf2d99c2bU, 0x19bd56ffU, 0x1a3e3d0dU, 0xeecd6d1eU, 0xed4e06ecU + /* 192 */ , 0xc4268dc3U, 0xc7a5e631U, 0x3356b622U, 0x30d5ddd0U, 0xdbb11704U, 0xd8327cf6U, 0x2cc12ce5U, 0x2f424717U + /* 200 */ , 0x0b7e5449U, 0x08fd3fbbU, 0xfc0e6fa8U, 0xff8d045aU, 0x14e9ce8eU, 0x176aa57cU, 0xe399f56fU, 0xe01a9e9dU + /* 208 */ , 0xabe1d3d3U, 0xa862b821U, 0x5c91e832U, 0x5f1283c0U, 0xb4764914U, 0xb7f522e6U, 0x430672f5U, 0x40851907U + /* 216 */ , 0x64b90a59U, 0x673a61abU, 0x93c931b8U, 0x904a5a4aU, 0x7b2e909eU, 0x78adfb6cU, 0x8c5eab7fU, 0x8fddc08dU + /* 224 */ , 0x1aa830e3U, 0x192b5b11U, 0xedd80b02U, 0xee5b60f0U, 0x053faa24U, 0x06bcc1d6U, 0xf24f91c5U, 0xf1ccfa37U + /* 232 */ , 0xd5f0e969U, 0xd673829bU, 0x2280d288U, 0x2103b97aU, 0xca6773aeU, 0xc9e4185cU, 0x3d17484fU, 0x3e9423bdU + /* 240 */ , 0x756f6ef3U, 0x76ec0501U, 0x821f5512U, 0x819c3ee0U, 0x6af8f434U, 0x697b9fc6U, 0x9d88cfd5U, 0x9e0ba427U + /* 248 */ , 0xba37b779U, 0xb9b4dc8bU, 0x4d478c98U, 0x4ec4e76aU, 0xa5a02dbeU, 0xa623464cU, 0x52d0165fU, 0x51537dadU + } + , + /* CRC32C table 5 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x7798a213U, 0xee304527U, 0x99a8e734U, 0xdc618a4eU, 0xabf9285dU, 0x3251cf69U, 0x45c96d7aU + /* 8 */ , 0xb8c3149dU, 0xcf5bb68eU, 0x56f351baU, 0x216bf3a9U, 0x64a29ed3U, 0x133a3cc0U, 0x8a92dbf4U, 0xfd0a79e7U + /* 16 */ , 0x81f1c53fU, 0xf669672cU, 0x6fc18018U, 0x1859220bU, 0x5d904f71U, 0x2a08ed62U, 0xb3a00a56U, 0xc438a845U + /* 24 */ , 0x3932d1a2U, 0x4eaa73b1U, 0xd7029485U, 0xa09a3696U, 0xe5535becU, 0x92cbf9ffU, 0x0b631ecbU, 0x7cfbbcd8U + /* 32 */ , 0x02e38b7fU, 0x757b296cU, 0xecd3ce58U, 0x9b4b6c4bU, 0xde820131U, 0xa91aa322U, 0x30b24416U, 0x472ae605U + /* 40 */ , 0xba209fe2U, 0xcdb83df1U, 0x5410dac5U, 0x238878d6U, 0x664115acU, 0x11d9b7bfU, 0x8871508bU, 0xffe9f298U + /* 48 */ , 0x83124e40U, 0xf48aec53U, 0x6d220b67U, 0x1abaa974U, 0x5f73c40eU, 0x28eb661dU, 0xb1438129U, 0xc6db233aU + /* 56 */ , 0x3bd15addU, 0x4c49f8ceU, 0xd5e11ffaU, 0xa279bde9U, 0xe7b0d093U, 0x90287280U, 0x098095b4U, 0x7e1837a7U + /* 64 */ , 0x04c617ffU, 0x735eb5ecU, 0xeaf652d8U, 0x9d6ef0cbU, 0xd8a79db1U, 0xaf3f3fa2U, 0x3697d896U, 0x410f7a85U + /* 72 */ , 0xbc050362U, 0xcb9da171U, 0x52354645U, 0x25ade456U, 0x6064892cU, 0x17fc2b3fU, 0x8e54cc0bU, 0xf9cc6e18U + /* 80 */ , 0x8537d2c0U, 0xf2af70d3U, 0x6b0797e7U, 0x1c9f35f4U, 0x5956588eU, 0x2ecefa9dU, 0xb7661da9U, 0xc0febfbaU + /* 88 */ , 0x3df4c65dU, 0x4a6c644eU, 0xd3c4837aU, 0xa45c2169U, 0xe1954c13U, 0x960dee00U, 0x0fa50934U, 0x783dab27U + /* 96 */ , 0x06259c80U, 0x71bd3e93U, 0xe815d9a7U, 0x9f8d7bb4U, 0xda4416ceU, 0xaddcb4ddU, 0x347453e9U, 0x43ecf1faU + /* 104 */ , 0xbee6881dU, 0xc97e2a0eU, 0x50d6cd3aU, 0x274e6f29U, 0x62870253U, 0x151fa040U, 0x8cb74774U, 0xfb2fe567U + /* 112 */ , 0x87d459bfU, 0xf04cfbacU, 0x69e41c98U, 0x1e7cbe8bU, 0x5bb5d3f1U, 0x2c2d71e2U, 0xb58596d6U, 0xc21d34c5U + /* 120 */ , 0x3f174d22U, 0x488fef31U, 0xd1270805U, 0xa6bfaa16U, 0xe376c76cU, 0x94ee657fU, 0x0d46824bU, 0x7ade2058U + /* 128 */ , 0xf9fac3fbU, 0x8e6261e8U, 0x17ca86dcU, 0x605224cfU, 0x259b49b5U, 0x5203eba6U, 0xcbab0c92U, 0xbc33ae81U + /* 136 */ , 0x4139d766U, 0x36a17575U, 0xaf099241U, 0xd8913052U, 0x9d585d28U, 0xeac0ff3bU, 0x7368180fU, 0x04f0ba1cU + /* 144 */ , 0x780b06c4U, 0x0f93a4d7U, 0x963b43e3U, 0xe1a3e1f0U, 0xa46a8c8aU, 0xd3f22e99U, 0x4a5ac9adU, 0x3dc26bbeU + /* 152 */ , 0xc0c81259U, 0xb750b04aU, 0x2ef8577eU, 0x5960f56dU, 0x1ca99817U, 0x6b313a04U, 0xf299dd30U, 0x85017f23U + /* 160 */ , 0xfb194884U, 0x8c81ea97U, 0x15290da3U, 0x62b1afb0U, 0x2778c2caU, 0x50e060d9U, 0xc94887edU, 0xbed025feU + /* 168 */ , 0x43da5c19U, 0x3442fe0aU, 0xadea193eU, 0xda72bb2dU, 0x9fbbd657U, 0xe8237444U, 0x718b9370U, 0x06133163U + /* 176 */ , 0x7ae88dbbU, 0x0d702fa8U, 0x94d8c89cU, 0xe3406a8fU, 0xa68907f5U, 0xd111a5e6U, 0x48b942d2U, 0x3f21e0c1U + /* 184 */ , 0xc22b9926U, 0xb5b33b35U, 0x2c1bdc01U, 0x5b837e12U, 0x1e4a1368U, 0x69d2b17bU, 0xf07a564fU, 0x87e2f45cU + /* 192 */ , 0xfd3cd404U, 0x8aa47617U, 0x130c9123U, 0x64943330U, 0x215d5e4aU, 0x56c5fc59U, 0xcf6d1b6dU, 0xb8f5b97eU + /* 200 */ , 0x45ffc099U, 0x3267628aU, 0xabcf85beU, 0xdc5727adU, 0x999e4ad7U, 0xee06e8c4U, 0x77ae0ff0U, 0x0036ade3U + /* 208 */ , 0x7ccd113bU, 0x0b55b328U, 0x92fd541cU, 0xe565f60fU, 0xa0ac9b75U, 0xd7343966U, 0x4e9cde52U, 0x39047c41U + /* 216 */ , 0xc40e05a6U, 0xb396a7b5U, 0x2a3e4081U, 0x5da6e292U, 0x186f8fe8U, 0x6ff72dfbU, 0xf65fcacfU, 0x81c768dcU + /* 224 */ , 0xffdf5f7bU, 0x8847fd68U, 0x11ef1a5cU, 0x6677b84fU, 0x23bed535U, 0x54267726U, 0xcd8e9012U, 0xba163201U + /* 232 */ , 0x471c4be6U, 0x3084e9f5U, 0xa92c0ec1U, 0xdeb4acd2U, 0x9b7dc1a8U, 0xece563bbU, 0x754d848fU, 0x02d5269cU + /* 240 */ , 0x7e2e9a44U, 0x09b63857U, 0x901edf63U, 0xe7867d70U, 0xa24f100aU, 0xd5d7b219U, 0x4c7f552dU, 0x3be7f73eU + /* 248 */ , 0xc6ed8ed9U, 0xb1752ccaU, 0x28ddcbfeU, 0x5f4569edU, 0x1a8c0497U, 0x6d14a684U, 0xf4bc41b0U, 0x8324e3a3U + } + , + /* CRC32C table 6 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0x7e9241a5U, 0x0d526f4fU, 0x73c02eeaU, 0x1aa4de9eU, 0x64369f3bU, 0x17f6b1d1U, 0x6964f074U + /* 8 */ , 0xc53e5138U, 0xbbac109dU, 0xc86c3e77U, 0xb6fe7fd2U, 0xdf9a8fa6U, 0xa108ce03U, 0xd2c8e0e9U, 0xac5aa14cU + /* 16 */ , 0x8a7da270U, 0xf4efe3d5U, 0x872fcd3fU, 0xf9bd8c9aU, 0x90d97ceeU, 0xee4b3d4bU, 0x9d8b13a1U, 0xe3195204U + /* 24 */ , 0x4f43f348U, 0x31d1b2edU, 0x42119c07U, 0x3c83dda2U, 0x55e72dd6U, 0x2b756c73U, 0x58b54299U, 0x2627033cU + /* 32 */ , 0x14fb44e1U, 0x6a690544U, 0x19a92baeU, 0x673b6a0bU, 0x0e5f9a7fU, 0x70cddbdaU, 0x030df530U, 0x7d9fb495U + /* 40 */ , 0xd1c515d9U, 0xaf57547cU, 0xdc977a96U, 0xa2053b33U, 0xcb61cb47U, 0xb5f38ae2U, 0xc633a408U, 0xb8a1e5adU + /* 48 */ , 0x9e86e691U, 0xe014a734U, 0x93d489deU, 0xed46c87bU, 0x8422380fU, 0xfab079aaU, 0x89705740U, 0xf7e216e5U + /* 56 */ , 0x5bb8b7a9U, 0x252af60cU, 0x56ead8e6U, 0x28789943U, 0x411c6937U, 0x3f8e2892U, 0x4c4e0678U, 0x32dc47ddU + /* 64 */ , 0xd98065c7U, 0xa7122462U, 0xd4d20a88U, 0xaa404b2dU, 0xc324bb59U, 0xbdb6fafcU, 0xce76d416U, 0xb0e495b3U + /* 72 */ , 0x1cbe34ffU, 0x622c755aU, 0x11ec5bb0U, 0x6f7e1a15U, 0x061aea61U, 0x7888abc4U, 0x0b48852eU, 0x75dac48bU + /* 80 */ , 0x53fdc7b7U, 0x2d6f8612U, 0x5eafa8f8U, 0x203de95dU, 0x49591929U, 0x37cb588cU, 0x440b7666U, 0x3a9937c3U + /* 88 */ , 0x96c3968fU, 0xe851d72aU, 0x9b91f9c0U, 0xe503b865U, 0x8c674811U, 0xf2f509b4U, 0x8135275eU, 0xffa766fbU + /* 96 */ , 0xcd7b2126U, 0xb3e96083U, 0xc0294e69U, 0xbebb0fccU, 0xd7dfffb8U, 0xa94dbe1dU, 0xda8d90f7U, 0xa41fd152U + /* 104 */ , 0x0845701eU, 0x76d731bbU, 0x05171f51U, 0x7b855ef4U, 0x12e1ae80U, 0x6c73ef25U, 0x1fb3c1cfU, 0x6121806aU + /* 112 */ , 0x47068356U, 0x3994c2f3U, 0x4a54ec19U, 0x34c6adbcU, 0x5da25dc8U, 0x23301c6dU, 0x50f03287U, 0x2e627322U + /* 120 */ , 0x8238d26eU, 0xfcaa93cbU, 0x8f6abd21U, 0xf1f8fc84U, 0x989c0cf0U, 0xe60e4d55U, 0x95ce63bfU, 0xeb5c221aU + /* 128 */ , 0x4377278bU, 0x3de5662eU, 0x4e2548c4U, 0x30b70961U, 0x59d3f915U, 0x2741b8b0U, 0x5481965aU, 0x2a13d7ffU + /* 136 */ , 0x864976b3U, 0xf8db3716U, 0x8b1b19fcU, 0xf5895859U, 0x9ceda82dU, 0xe27fe988U, 0x91bfc762U, 0xef2d86c7U + /* 144 */ , 0xc90a85fbU, 0xb798c45eU, 0xc458eab4U, 0xbacaab11U, 0xd3ae5b65U, 0xad3c1ac0U, 0xdefc342aU, 0xa06e758fU + /* 152 */ , 0x0c34d4c3U, 0x72a69566U, 0x0166bb8cU, 0x7ff4fa29U, 0x16900a5dU, 0x68024bf8U, 0x1bc26512U, 0x655024b7U + /* 160 */ , 0x578c636aU, 0x291e22cfU, 0x5ade0c25U, 0x244c4d80U, 0x4d28bdf4U, 0x33bafc51U, 0x407ad2bbU, 0x3ee8931eU + /* 168 */ , 0x92b23252U, 0xec2073f7U, 0x9fe05d1dU, 0xe1721cb8U, 0x8816ecccU, 0xf684ad69U, 0x85448383U, 0xfbd6c226U + /* 176 */ , 0xddf1c11aU, 0xa36380bfU, 0xd0a3ae55U, 0xae31eff0U, 0xc7551f84U, 0xb9c75e21U, 0xca0770cbU, 0xb495316eU + /* 184 */ , 0x18cf9022U, 0x665dd187U, 0x159dff6dU, 0x6b0fbec8U, 0x026b4ebcU, 0x7cf90f19U, 0x0f3921f3U, 0x71ab6056U + /* 192 */ , 0x9af7424cU, 0xe46503e9U, 0x97a52d03U, 0xe9376ca6U, 0x80539cd2U, 0xfec1dd77U, 0x8d01f39dU, 0xf393b238U + /* 200 */ , 0x5fc91374U, 0x215b52d1U, 0x529b7c3bU, 0x2c093d9eU, 0x456dcdeaU, 0x3bff8c4fU, 0x483fa2a5U, 0x36ade300U + /* 208 */ , 0x108ae03cU, 0x6e18a199U, 0x1dd88f73U, 0x634aced6U, 0x0a2e3ea2U, 0x74bc7f07U, 0x077c51edU, 0x79ee1048U + /* 216 */ , 0xd5b4b104U, 0xab26f0a1U, 0xd8e6de4bU, 0xa6749feeU, 0xcf106f9aU, 0xb1822e3fU, 0xc24200d5U, 0xbcd04170U + /* 224 */ , 0x8e0c06adU, 0xf09e4708U, 0x835e69e2U, 0xfdcc2847U, 0x94a8d833U, 0xea3a9996U, 0x99fab77cU, 0xe768f6d9U + /* 232 */ , 0x4b325795U, 0x35a01630U, 0x466038daU, 0x38f2797fU, 0x5196890bU, 0x2f04c8aeU, 0x5cc4e644U, 0x2256a7e1U + /* 240 */ , 0x0471a4ddU, 0x7ae3e578U, 0x0923cb92U, 0x77b18a37U, 0x1ed57a43U, 0x60473be6U, 0x1387150cU, 0x6d1554a9U + /* 248 */ , 0xc14ff5e5U, 0xbfddb440U, 0xcc1d9aaaU, 0xb28fdb0fU, 0xdbeb2b7bU, 0xa5796adeU, 0xd6b94434U, 0xa82b0591U + } + , + /* CRC32C table 7 for quad-bytes ( big-endian ), auto-generated. DO NOT MODIFY! */ + { + /* 0 */ 0x00000000U, 0xb8aa45ddU, 0x812367bfU, 0x39892262U, 0xf331227bU, 0x4b9b67a6U, 0x721245c4U, 0xcab80019U + /* 8 */ , 0xe66344f6U, 0x5ec9012bU, 0x67402349U, 0xdfea6694U, 0x1552668dU, 0xadf82350U, 0x94710132U, 0x2cdb44efU + /* 16 */ , 0x3db164e9U, 0x851b2134U, 0xbc920356U, 0x0438468bU, 0xce804692U, 0x762a034fU, 0x4fa3212dU, 0xf70964f0U + /* 24 */ , 0xdbd2201fU, 0x637865c2U, 0x5af147a0U, 0xe25b027dU, 0x28e30264U, 0x904947b9U, 0xa9c065dbU, 0x116a2006U + /* 32 */ , 0x8b1425d7U, 0x33be600aU, 0x0a374268U, 0xb29d07b5U, 0x782507acU, 0xc08f4271U, 0xf9066013U, 0x41ac25ceU + /* 40 */ , 0x6d776121U, 0xd5dd24fcU, 0xec54069eU, 0x54fe4343U, 0x9e46435aU, 0x26ec0687U, 0x1f6524e5U, 0xa7cf6138U + /* 48 */ , 0xb6a5413eU, 0x0e0f04e3U, 0x37862681U, 0x8f2c635cU, 0x45946345U, 0xfd3e2698U, 0xc4b704faU, 0x7c1d4127U + /* 56 */ , 0x50c605c8U, 0xe86c4015U, 0xd1e56277U, 0x694f27aaU, 0xa3f727b3U, 0x1b5d626eU, 0x22d4400cU, 0x9a7e05d1U + /* 64 */ , 0xe75fa6abU, 0x5ff5e376U, 0x667cc114U, 0xded684c9U, 0x146e84d0U, 0xacc4c10dU, 0x954de36fU, 0x2de7a6b2U + /* 72 */ , 0x013ce25dU, 0xb996a780U, 0x801f85e2U, 0x38b5c03fU, 0xf20dc026U, 0x4aa785fbU, 0x732ea799U, 0xcb84e244U + /* 80 */ , 0xdaeec242U, 0x6244879fU, 0x5bcda5fdU, 0xe367e020U, 0x29dfe039U, 0x9175a5e4U, 0xa8fc8786U, 0x1056c25bU + /* 88 */ , 0x3c8d86b4U, 0x8427c369U, 0xbdaee10bU, 0x0504a4d6U, 0xcfbca4cfU, 0x7716e112U, 0x4e9fc370U, 0xf63586adU + /* 96 */ , 0x6c4b837cU, 0xd4e1c6a1U, 0xed68e4c3U, 0x55c2a11eU, 0x9f7aa107U, 0x27d0e4daU, 0x1e59c6b8U, 0xa6f38365U + /* 104 */ , 0x8a28c78aU, 0x32828257U, 0x0b0ba035U, 0xb3a1e5e8U, 0x7919e5f1U, 0xc1b3a02cU, 0xf83a824eU, 0x4090c793U + /* 112 */ , 0x51fae795U, 0xe950a248U, 0xd0d9802aU, 0x6873c5f7U, 0xa2cbc5eeU, 0x1a618033U, 0x23e8a251U, 0x9b42e78cU + /* 120 */ , 0xb799a363U, 0x0f33e6beU, 0x36bac4dcU, 0x8e108101U, 0x44a88118U, 0xfc02c4c5U, 0xc58be6a7U, 0x7d21a37aU + /* 128 */ , 0x3fc9a052U, 0x8763e58fU, 0xbeeac7edU, 0x06408230U, 0xccf88229U, 0x7452c7f4U, 0x4ddbe596U, 0xf571a04bU + /* 136 */ , 0xd9aae4a4U, 0x6100a179U, 0x5889831bU, 0xe023c6c6U, 0x2a9bc6dfU, 0x92318302U, 0xabb8a160U, 0x1312e4bdU + /* 144 */ , 0x0278c4bbU, 0xbad28166U, 0x835ba304U, 0x3bf1e6d9U, 0xf149e6c0U, 0x49e3a31dU, 0x706a817fU, 0xc8c0c4a2U + /* 152 */ , 0xe41b804dU, 0x5cb1c590U, 0x6538e7f2U, 0xdd92a22fU, 0x172aa236U, 0xaf80e7ebU, 0x9609c589U, 0x2ea38054U + /* 160 */ , 0xb4dd8585U, 0x0c77c058U, 0x35fee23aU, 0x8d54a7e7U, 0x47eca7feU, 0xff46e223U, 0xc6cfc041U, 0x7e65859cU + /* 168 */ , 0x52bec173U, 0xea1484aeU, 0xd39da6ccU, 0x6b37e311U, 0xa18fe308U, 0x1925a6d5U, 0x20ac84b7U, 0x9806c16aU + /* 176 */ , 0x896ce16cU, 0x31c6a4b1U, 0x084f86d3U, 0xb0e5c30eU, 0x7a5dc317U, 0xc2f786caU, 0xfb7ea4a8U, 0x43d4e175U + /* 184 */ , 0x6f0fa59aU, 0xd7a5e047U, 0xee2cc225U, 0x568687f8U, 0x9c3e87e1U, 0x2494c23cU, 0x1d1de05eU, 0xa5b7a583U + /* 192 */ , 0xd89606f9U, 0x603c4324U, 0x59b56146U, 0xe11f249bU, 0x2ba72482U, 0x930d615fU, 0xaa84433dU, 0x122e06e0U + /* 200 */ , 0x3ef5420fU, 0x865f07d2U, 0xbfd625b0U, 0x077c606dU, 0xcdc46074U, 0x756e25a9U, 0x4ce707cbU, 0xf44d4216U + /* 208 */ , 0xe5276210U, 0x5d8d27cdU, 0x640405afU, 0xdcae4072U, 0x1616406bU, 0xaebc05b6U, 0x973527d4U, 0x2f9f6209U + /* 216 */ , 0x034426e6U, 0xbbee633bU, 0x82674159U, 0x3acd0484U, 0xf075049dU, 0x48df4140U, 0x71566322U, 0xc9fc26ffU + /* 224 */ , 0x5382232eU, 0xeb2866f3U, 0xd2a14491U, 0x6a0b014cU, 0xa0b30155U, 0x18194488U, 0x219066eaU, 0x993a2337U + /* 232 */ , 0xb5e167d8U, 0x0d4b2205U, 0x34c20067U, 0x8c6845baU, 0x46d045a3U, 0xfe7a007eU, 0xc7f3221cU, 0x7f5967c1U + /* 240 */ , 0x6e3347c7U, 0xd699021aU, 0xef102078U, 0x57ba65a5U, 0x9d0265bcU, 0x25a82061U, 0x1c210203U, 0xa48b47deU + /* 248 */ , 0x88500331U, 0x30fa46ecU, 0x0973648eU, 0xb1d92153U, 0x7b61214aU, 0xc3cb6497U, 0xfa4246f5U, 0x42e80328U + } + #endif + }; diff --git a/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp b/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp index 5bb64303b6b..b2509b23094 100644 --- a/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp +++ b/hotspot/src/cpu/s390/vm/stubRoutines_s390.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. 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 @@ -68,12 +68,11 @@ class zarch { }; private: - static address _handler_for_unsafe_access_entry; - static int _atomic_memory_operation_lock; static address _partial_subtype_check; static juint _crc_table[CRC32_TABLES][CRC32_COLUMN_SIZE]; + static juint _crc32c_table[CRC32_TABLES][CRC32_COLUMN_SIZE]; // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. static address _trot_table_addr; @@ -91,11 +90,11 @@ class zarch { static int atomic_memory_operation_lock() { return _atomic_memory_operation_lock; } static void set_atomic_memory_operation_lock(int value) { _atomic_memory_operation_lock = value; } - static address handler_for_unsafe_access_entry() { return _handler_for_unsafe_access_entry; } - static address partial_subtype_check() { return _partial_subtype_check; } + static void generate_load_absolute_address(MacroAssembler* masm, Register table, address table_addr, uint64_t table_contents); static void generate_load_crc_table_addr(MacroAssembler* masm, Register table); + static void generate_load_crc32c_table_addr(MacroAssembler* masm, Register table); // Comapct string intrinsics: Translate table for string inflate intrinsic. Used by trot instruction. static void generate_load_trot_table_addr(MacroAssembler* masm, Register table); diff --git a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp index 20a9a3e9571..5d94689b383 100644 --- a/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp +++ b/hotspot/src/cpu/s390/vm/templateInterpreterGenerator_s390.cpp @@ -1,6 +1,6 @@ /* * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016, 2017 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, SAP SE. 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 @@ -121,9 +121,8 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { // We use target_sp for storing arguments in the C frame. __ save_return_pc(); - - __ z_stmg(Z_R10,Z_R13,-32,Z_SP); - __ push_frame_abi160(32); + __ push_frame_abi160(4*BytesPerWord); // Reserve space to save the tmp_[1..4] registers. + __ z_stmg(Z_R10, Z_R13, frame::z_abi_160_size, Z_SP); // Save registers only after frame is pushed. __ z_lgr(arg_java, Z_ARG1); @@ -341,9 +340,9 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { // Method exit, all arguments proocessed. __ bind(loop_end); + __ z_lmg(Z_R10, Z_R13, frame::z_abi_160_size, Z_SP); // restore registers before frame is popped. __ pop_frame(); __ restore_return_pc(); - __ z_lmg(Z_R10,Z_R13,-32,Z_SP); __ z_br(Z_R14); // Copy int arguments. @@ -642,13 +641,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common(const ch return entry; } -// Unused, should never pass by. -address TemplateInterpreterGenerator::generate_continuation_for (TosState state) { - address entry = __ pc(); - __ should_not_reach_here(); - return entry; -} - address TemplateInterpreterGenerator::generate_return_entry_for (TosState state, int step, size_t index_size) { address entry = __ pc(); @@ -683,6 +675,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for (TosState state, __ z_llgc(size, Address(cache, offset, flags_offset+(sizeof(size_t)-1))); __ z_sllg(size, size, Interpreter::logStackElementSize); // Each argument size in bytes. __ z_agr(Z_esp, size); // Pop arguments. + + __ check_and_handle_popframe(Z_thread); + __ check_and_handle_earlyret(Z_thread); + __ dispatch_next(state, step); BLOCK_COMMENT("} return_entry"); @@ -1186,11 +1182,6 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { // native_call: assert that mdo == NULL const bool check_for_mdo = !native_call DEBUG_ONLY(|| native_call); if (ProfileInterpreter && check_for_mdo) { -#ifdef FAST_DISPATCH - // FAST_DISPATCH and ProfileInterpreter are mutually exclusive since - // they both use I2. - assert(0, "FAST_DISPATCH and +ProfileInterpreter are mutually exclusive"); -#endif // FAST_DISPATCH Label get_continue; __ load_and_test_long(Rmdp, method_(method_data)); @@ -1240,13 +1231,9 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { // Advance local_addr to point behind locals (creates positive incr. in loop). __ z_lg(Z_R1_scratch, Address(Z_method, Method::const_offset())); - __ z_llgh(Z_R0_scratch, - Address(Z_R1_scratch, ConstMethod::size_of_locals_offset())); - if (Z_R0_scratch == Z_R0) { - __ z_aghi(Z_R0_scratch, -1); - } else { - __ add2reg(Z_R0_scratch, -1); - } + __ z_llgh(Z_R0_scratch, Address(Z_R1_scratch, ConstMethod::size_of_locals_offset())); + __ add2reg(Z_R0_scratch, -1); + __ z_lgr(local_addr/*locals*/, Z_locals); __ z_sllg(Z_R0_scratch, Z_R0_scratch, LogBytesPerWord); __ z_sllg(local_count, local_count, LogBytesPerWord); // Local_count are non param locals. @@ -1933,8 +1920,11 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { return entry_point; } -// Method entry for static native methods: -// int java.util.zip.CRC32.update(int crc, int b) + +/** + * Method entry for static native methods: + * int java.util.zip.CRC32.update(int crc, int b) + */ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { if (UseCRC32Intrinsics) { @@ -1964,7 +1954,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { __ z_llgf(crc, 2 * wordSize, argP); // Current crc state, zero extend to 64 bit to have a clean register. StubRoutines::zarch::generate_load_crc_table_addr(_masm, table); - __ kernel_crc32_singleByte(crc, data, dataLen, table, Z_R1); + __ kernel_crc32_singleByte(crc, data, dataLen, table, Z_R1, true); // Restore caller sp for c2i case. __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started. @@ -1983,9 +1973,11 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { } -// Method entry for static native methods: -// int java.util.zip.CRC32.updateBytes(int crc, byte[] b, int off, int len) -// int java.util.zip.CRC32.updateByteBuffer(int crc, long buf, int off, int len) +/** + * Method entry for static native methods: + * int java.util.zip.CRC32.updateBytes( int crc, byte[] b, int off, int len) + * int java.util.zip.CRC32.updateByteBuffer(int crc, long* buf, int off, int len) + */ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpreter::MethodKind kind) { if (UseCRC32Intrinsics) { @@ -2020,10 +2012,10 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI // data = buf + off BLOCK_COMMENT("CRC32_updateByteBuffer {"); __ z_llgf(crc, 5*wordSize, argP); // current crc state - __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_lg(data, 3*wordSize, argP); // start of byte buffer __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process - } else { // Used for "updateBytes update". + } else { // Used for "updateBytes update". // crc @ (SP + 4W) (32bit) // buf @ (SP + 3W) (64bit ptr to byte array) // off @ (SP + 2W) (32bit) @@ -2031,7 +2023,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI // data = buf + off + base_offset BLOCK_COMMENT("CRC32_updateBytes {"); __ z_llgf(crc, 4*wordSize, argP); // current crc state - __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_lg(data, 3*wordSize, argP); // start of byte buffer __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process __ z_aghi(data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); @@ -2041,7 +2033,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. __ z_stmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 to make them available as work registers. - __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3); + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, true); __ z_lmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 back from stack. // Restore caller sp for c2i case. @@ -2060,8 +2052,79 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI return NULL; } -// Not supported + +/** + * Method entry for intrinsic-candidate (non-native) methods: + * int java.util.zip.CRC32C.updateBytes( int crc, byte[] b, int off, int end) + * int java.util.zip.CRC32C.updateDirectByteBuffer(int crc, long* buf, int off, int end) + * Unlike CRC32, CRC32C does not have any methods marked as native + * CRC32C also uses an "end" variable instead of the length variable CRC32 uses + */ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(AbstractInterpreter::MethodKind kind) { + + if (UseCRC32CIntrinsics) { + uint64_t entry_off = __ offset(); + + // We don't generate local frame and don't align stack because + // we call stub code and there is no safepoint on this path. + + // Load parameters. + // Z_esp is callers operand stack pointer, i.e. it points to the parameters. + const Register argP = Z_esp; + const Register crc = Z_ARG1; // crc value + const Register data = Z_ARG2; // address of java byte array + const Register dataLen = Z_ARG3; // source data len + const Register table = Z_ARG4; // address of crc32 table + const Register t0 = Z_R10; // work reg for kernel* emitters + const Register t1 = Z_R11; // work reg for kernel* emitters + const Register t2 = Z_R12; // work reg for kernel* emitters + const Register t3 = Z_R13; // work reg for kernel* emitters + + // Arguments are reversed on java expression stack. + // Calculate address of start element. + if (kind == Interpreter::java_util_zip_CRC32C_updateDirectByteBuffer) { // Used for "updateByteBuffer direct". + // crc @ (SP + 5W) (32bit) + // buf @ (SP + 3W) (64bit ptr to long array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + BLOCK_COMMENT("CRC32C_updateDirectByteBuffer {"); + __ z_llgf(crc, 5*wordSize, argP); // current crc state + __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. + __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process, calculated as + __ z_sgf(dataLen, Address(argP, 2*wordSize)); // (end_index - offset) + } else { // Used for "updateBytes update". + // crc @ (SP + 4W) (32bit) + // buf @ (SP + 3W) (64bit ptr to byte array) + // off @ (SP + 2W) (32bit) + // dataLen @ (SP + 1W) (32bit) + // data = buf + off + base_offset + BLOCK_COMMENT("CRC32C_updateBytes {"); + __ z_llgf(crc, 4*wordSize, argP); // current crc state + __ z_lg(data, 3*wordSize, argP); // start of byte buffer + __ z_agf(data, 2*wordSize, argP); // Add byte buffer offset. + __ z_lgf(dataLen, 1*wordSize, argP); // #bytes to process, calculated as + __ z_sgf(dataLen, Address(argP, 2*wordSize)); // (end_index - offset) + __ z_aghi(data, arrayOopDesc::base_offset_in_bytes(T_BYTE)); + } + + StubRoutines::zarch::generate_load_crc32c_table_addr(_masm, table); + + __ resize_frame(-(6*8), Z_R0, true); // Resize frame to provide add'l space to spill 5 registers. + __ z_stmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 to make them available as work registers. + __ kernel_crc32_1word(crc, data, dataLen, table, t0, t1, t2, t3, false); + __ z_lmg(t0, t3, 1*8, Z_SP); // Spill regs 10..13 back from stack. + + // Restore caller sp for c2i case. + __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started. + + __ z_br(Z_R14); + + BLOCK_COMMENT("} CRC32C_update{Bytes|DirectByteBuffer}"); + return __ addr_at(entry_off); + } + return NULL; } diff --git a/hotspot/src/cpu/s390/vm/templateTable_s390.cpp b/hotspot/src/cpu/s390/vm/templateTable_s390.cpp index 83d707dbd60..becbb0e48b5 100644 --- a/hotspot/src/cpu/s390/vm/templateTable_s390.cpp +++ b/hotspot/src/cpu/s390/vm/templateTable_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017 SAP SE. 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 @@ -3466,7 +3466,7 @@ void TemplateTable::invokevirtual_helper(Register index, __ z_sllg(index, index, exact_log2(vtableEntry::size_in_bytes())); __ mem2reg_opt(method, Address(Z_tmp_2, index, - InstanceKlass::vtable_start_offset() + in_ByteSize(vtableEntry::method_offset_in_bytes()))); + Klass::vtable_start_offset() + in_ByteSize(vtableEntry::method_offset_in_bytes()))); __ profile_arguments_type(Z_ARG4, method, Z_ARG5, true); __ jump_from_interpreted(method, Z_ARG4); BLOCK_COMMENT("} invokevirtual_helper"); @@ -3708,7 +3708,7 @@ void TemplateTable::_new() { __ z_sllg(offset, offset, LogBytesPerWord); // Convert to to offset. // Get InstanceKlass. Register iklass = cpool; - __ z_lg(iklass, Address(cpool, offset, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(cpool, offset, iklass); // Make sure klass is initialized & doesn't have finalizer. // Make sure klass is fully initialized. @@ -3895,7 +3895,7 @@ void TemplateTable::checkcast() { __ z_lgr(Z_ARG4, Z_tos); // Save receiver. __ z_sllg(index, index, LogBytesPerWord); // index2bytes for addressing - __ mem2reg_opt(klass, Address(cpool, index, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(cpool, index, klass); __ bind(resolved); @@ -3969,8 +3969,7 @@ void TemplateTable::instanceof() { __ load_klass(subklass, Z_tos); __ z_sllg(index, index, LogBytesPerWord); // index2bytes for addressing - __ mem2reg_opt(klass, - Address(cpool, index, sizeof(ConstantPool))); + __ load_resolved_klass_at_offset(cpool, index, klass); __ bind(resolved); diff --git a/hotspot/src/cpu/s390/vm/vm_version_s390.cpp b/hotspot/src/cpu/s390/vm/vm_version_s390.cpp index 55dbd30aec8..709a9fdf6ed 100644 --- a/hotspot/src/cpu/s390/vm/vm_version_s390.cpp +++ b/hotspot/src/cpu/s390/vm/vm_version_s390.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2016 SAP SE. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017 SAP SE. 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 @@ -28,6 +28,7 @@ #include "compiler/disassembler.hpp" #include "code/compiledIC.hpp" #include "memory/resourceArea.hpp" +#include "prims/jvm.h" #include "runtime/java.hpp" #include "runtime/stubCodeGenerator.hpp" #include "vm_version_s390.hpp" @@ -111,13 +112,23 @@ void VM_Version::initialize() { ContendedPaddingWidth = cache_line_size; } - // On z/Architecture, the CRC32 intrinsics had to be implemented "by hand". - // They cannot be based on the CHECKSUM instruction which has been there - // since the very beginning (of z/Architecture). It computes "some kind of" a checksum - // which has nothing to do with the CRC32 algorithm. + // On z/Architecture, the CRC32/CRC32C intrinsics are implemented "by hand". + // TODO: Provide implementation based on the vector instructions available from z13. + // Note: The CHECKSUM instruction, which has been there since the very beginning + // (of z/Architecture), computes "some kind of" a checksum. + // It has nothing to do with the CRC32 algorithm. if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { FLAG_SET_DEFAULT(UseCRC32Intrinsics, true); } + if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) { + FLAG_SET_DEFAULT(UseCRC32CIntrinsics, true); + } + + // TODO: Provide implementation. + if (UseAdler32Intrinsics) { + warning("Adler32Intrinsics not available on this CPU."); + FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); + } // On z/Architecture, we take UseAES as the general switch to enable/disable the AES intrinsics. // The specific, and yet to be defined, switches UseAESxxxIntrinsics will then be set @@ -142,6 +153,10 @@ void VM_Version::initialize() { warning("AES intrinsics are not available on this CPU"); FLAG_SET_DEFAULT(UseAESIntrinsics, false); } + if (UseAESIntrinsics && !UseAES) { + warning("AES intrinsics require UseAES flag to be enabled. Intrinsics will be disabled."); + FLAG_SET_DEFAULT(UseAESIntrinsics, false); + } // TODO: implement AES/CTR intrinsics if (UseAESCTRIntrinsics) { @@ -195,11 +210,6 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } - if (UseAdler32Intrinsics) { - warning("Adler32Intrinsics not available on this CPU."); - FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); - } - if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true); } diff --git a/hotspot/src/cpu/s390/vm/vtableStubs_s390.cpp b/hotspot/src/cpu/s390/vm/vtableStubs_s390.cpp index c2c3ab246b8..de0a351ea04 100644 --- a/hotspot/src/cpu/s390/vm/vtableStubs_s390.cpp +++ b/hotspot/src/cpu/s390/vm/vtableStubs_s390.cpp @@ -83,7 +83,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { __ load_klass(rcvr_klass, Z_ARG1); // Set method (in case of interpreted method), and destination address. - int entry_offset = in_bytes(InstanceKlass::vtable_start_offset()) + + int entry_offset = in_bytes(Klass::vtable_start_offset()) + vtable_index * vtableEntry::size_in_bytes(); #ifndef PRODUCT @@ -96,8 +96,8 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { // worst case actual size padding_bytes += __ load_const_size() - __ load_const_optimized_rtn_len(vtable_idx, vtable_index*vtableEntry::size_in_bytes(), true); - assert(Immediate::is_uimm12(in_bytes(InstanceKlass::vtable_length_offset())), "disp to large"); - __ z_cl(vtable_idx, in_bytes(InstanceKlass::vtable_length_offset()), rcvr_klass); + assert(Immediate::is_uimm12(in_bytes(Klass::vtable_length_offset())), "disp to large"); + __ z_cl(vtable_idx, in_bytes(Klass::vtable_length_offset()), rcvr_klass); __ z_brl(L); __ z_lghi(Z_ARG3, vtable_index); // Debug code, don't optimize. __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), Z_ARG1, Z_ARG3, false); @@ -187,11 +187,11 @@ VtableStub* VtableStubs::create_itable_stub(int vtable_index) { __ load_klass(rcvr_klass, Z_ARG1); // Load start of itable entries into itable_entry. - __ z_llgf(vtable_len, Address(rcvr_klass, InstanceKlass::vtable_length_offset())); + __ z_llgf(vtable_len, Address(rcvr_klass, Klass::vtable_length_offset())); __ z_sllg(vtable_len, vtable_len, exact_log2(vtableEntry::size_in_bytes())); // Loop over all itable entries until desired interfaceOop(Rinterface) found. - const int vtable_base_offset = in_bytes(InstanceKlass::vtable_start_offset()); + const int vtable_base_offset = in_bytes(Klass::vtable_start_offset()); // Count unused bytes. start_pc = __ pc(); __ add2reg_with_index(itable_entry_addr, vtable_base_offset + itableOffsetEntry::interface_offset_in_bytes(), rcvr_klass, vtable_len); diff --git a/hotspot/src/cpu/sparc/vm/abstractInterpreter_sparc.cpp b/hotspot/src/cpu/sparc/vm/abstractInterpreter_sparc.cpp index f9ba7983fd2..c96f1fe978d 100644 --- a/hotspot/src/cpu/sparc/vm/abstractInterpreter_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/abstractInterpreter_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -29,6 +29,7 @@ #include "runtime/arguments.hpp" #include "runtime/frame.inline.hpp" #include "runtime/synchronizer.hpp" +#include "utilities/align.hpp" #include "utilities/macros.hpp" @@ -52,11 +53,6 @@ int AbstractInterpreter::BasicType_as_index(BasicType type) { return i; } -bool AbstractInterpreter::can_be_compiled(methodHandle m) { - // No special entry points that preclude compilation - return true; -} - static int size_activation_helper(int callee_extra_locals, int max_stack, int monitor_size) { // Figure out the size of an interpreter frame (in words) given that we have a fully allocated @@ -71,12 +67,12 @@ static int size_activation_helper(int callee_extra_locals, int max_stack, int mo // the caller so we must ensure that it is properly aligned for our callee. // const int rounded_vm_local_words = - round_to(frame::interpreter_frame_vm_local_words,WordsPerLong); + align_up((int)frame::interpreter_frame_vm_local_words,WordsPerLong); // callee_locals and max_stack are counts, not the size in frame. const int locals_size = - round_to(callee_extra_locals * Interpreter::stackElementWords, WordsPerLong); + align_up(callee_extra_locals * Interpreter::stackElementWords, WordsPerLong); const int max_stack_words = max_stack * Interpreter::stackElementWords; - return (round_to((max_stack_words + return (align_up((max_stack_words + rounded_vm_local_words + frame::memory_parameter_word_sp_offset), WordsPerLong) // already rounded @@ -87,7 +83,7 @@ static int size_activation_helper(int callee_extra_locals, int max_stack, int mo int AbstractInterpreter::size_top_interpreter_activation(Method* method) { // See call_stub code - int call_stub_size = round_to(7 + frame::memory_parameter_word_sp_offset, + int call_stub_size = align_up(7 + frame::memory_parameter_word_sp_offset, WordsPerLong); // 7 + register save area // Save space for one monitor to get into the interpreted method in case @@ -110,7 +106,7 @@ int AbstractInterpreter::size_activation(int max_stack, int monitor_size = monitors * frame::interpreter_frame_monitor_size(); - assert(monitor_size == round_to(monitor_size, WordsPerLong), "must align"); + assert(is_aligned(monitor_size, WordsPerLong), "must align"); // // Note: if you look closely this appears to be doing something much different @@ -136,8 +132,8 @@ int AbstractInterpreter::size_activation(int max_stack, // there is no sense in messing working code. // - int rounded_cls = round_to((callee_locals - callee_params), WordsPerLong); - assert(rounded_cls == round_to(rounded_cls, WordsPerLong), "must align"); + int rounded_cls = align_up((callee_locals - callee_params), WordsPerLong); + assert(is_aligned(rounded_cls, WordsPerLong), "must align"); int raw_frame_size = size_activation_helper(rounded_cls, max_stack, monitor_size); @@ -171,9 +167,9 @@ void AbstractInterpreter::layout_activation(Method* method, // even if not fully filled out. assert(interpreter_frame->is_interpreted_frame(), "Must be interpreted frame"); - int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words,WordsPerLong); + int rounded_vm_local_words = align_up((int)frame::interpreter_frame_vm_local_words,WordsPerLong); int monitor_size = moncount * frame::interpreter_frame_monitor_size(); - assert(monitor_size == round_to(monitor_size, WordsPerLong), "must align"); + assert(is_aligned(monitor_size, WordsPerLong), "must align"); intptr_t* fp = interpreter_frame->fp(); @@ -203,7 +199,7 @@ void AbstractInterpreter::layout_activation(Method* method, int parm_words = caller_actual_parameters * Interpreter::stackElementWords; locals = Lesp_ptr + parm_words; int delta = local_words - parm_words; - int computed_sp_adjustment = (delta > 0) ? round_to(delta, WordsPerLong) : 0; + int computed_sp_adjustment = (delta > 0) ? align_up(delta, WordsPerLong) : 0; *interpreter_frame->register_addr(I5_savedSP) = (intptr_t) (fp + computed_sp_adjustment) - STACK_BIAS; if (!is_bottom_frame) { // Llast_SP is set below for the current frame to SP (with the @@ -270,9 +266,7 @@ void AbstractInterpreter::layout_activation(Method* method, assert(locals < interpreter_frame->sp() || locals > (interpreter_frame->sp() + 16), "locals in save area"); assert(locals < interpreter_frame->fp() || locals >= (interpreter_frame->fp() + 16), "locals in save area"); } -#ifdef _LP64 assert(*interpreter_frame->register_addr(I5_savedSP) & 1, "must be odd"); -#endif *interpreter_frame->register_addr(Lmethod) = (intptr_t) method; *interpreter_frame->register_addr(Llocals) = (intptr_t) locals; @@ -283,9 +277,6 @@ void AbstractInterpreter::layout_activation(Method* method, *interpreter_frame->register_addr(LcpoolCache) = (intptr_t) method->constants()->cache(); // save the mirror in the interpreter frame *interpreter_frame->interpreter_frame_mirror_addr() = method->method_holder()->java_mirror(); -#ifdef FAST_DISPATCH - *interpreter_frame->register_addr(IdispatchTables) = (intptr_t) Interpreter::dispatch_table(); -#endif #ifdef ASSERT BasicObjectLock* mp = (BasicObjectLock*)monitors; diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp index 2cc945ad2a1..61c789bf83c 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.cpp @@ -26,6 +26,36 @@ #include "asm/assembler.hpp" #include "asm/assembler.inline.hpp" +#include "assembler_sparc.hpp" + int AbstractAssembler::code_fill_byte() { return 0x00; // illegal instruction 0x00000000 } + +#ifdef VALIDATE_PIPELINE +/* Walk over the current code section and verify that there are no obvious + * pipeline hazards exposed in the code generated. + */ +void Assembler::validate_no_pipeline_hazards() { + const CodeSection* csect = code_section(); + + address addr0 = csect->start(); + address addrN = csect->end(); + uint32_t prev = 0; + + assert((addrN - addr0) % BytesPerInstWord == 0, "must be"); + + for (address pc = addr0; pc != addrN; pc += BytesPerInstWord) { + uint32_t insn = *reinterpret_cast(pc); + + // 1. General case: No CTI immediately after other CTI + assert(!(is_cti(prev) && is_cti(insn)), "CTI-CTI not allowed."); + + // 2. Special case: No CTI immediately after/before RDPC + assert(!(is_cti(prev) && is_rdpc(insn)), "CTI-RDPC not allowed."); + assert(!(is_rdpc(prev) && is_cti(insn)), "RDPC-CTI not allowed."); + + prev = insn; + } +} +#endif diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp index ec1a2423aa0..69822951928 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -28,10 +28,10 @@ #include "asm/register.hpp" // The SPARC Assembler: Pure assembler doing NO optimizations on the instruction -// level; i.e., what you write -// is what you get. The Assembler is generating code into a CodeBuffer. +// level; i.e., what you write is what you get. The Assembler is generating code +// into a CodeBuffer. -class Assembler : public AbstractAssembler { +class Assembler : public AbstractAssembler { friend class AbstractAssembler; friend class AddressLiteral; @@ -244,18 +244,18 @@ class Assembler : public AbstractAssembler { }; enum op5s { - aes_eround01_op5 = 0x00, - aes_eround23_op5 = 0x01, - aes_dround01_op5 = 0x02, - aes_dround23_op5 = 0x03, - aes_eround01_l_op5 = 0x04, - aes_eround23_l_op5 = 0x05, - aes_dround01_l_op5 = 0x06, - aes_dround23_l_op5 = 0x07, - aes_kexpand1_op5 = 0x08 + aes_eround01_op5 = 0x00, + aes_eround23_op5 = 0x01, + aes_dround01_op5 = 0x02, + aes_dround23_op5 = 0x03, + aes_eround01_l_op5 = 0x04, + aes_eround23_l_op5 = 0x05, + aes_dround01_l_op5 = 0x06, + aes_dround23_l_op5 = 0x07, + aes_kexpand1_op5 = 0x08 }; - enum RCondition { rc_z = 1, rc_lez = 2, rc_lz = 3, rc_nz = 5, rc_gz = 6, rc_gez = 7, rc_last = rc_gez }; + enum RCondition { rc_z = 1, rc_lez = 2, rc_lz = 3, rc_nz = 5, rc_gz = 6, rc_gez = 7, rc_last = rc_gez }; enum Condition { // for FBfcc & FBPfcc instruction @@ -278,59 +278,38 @@ class Assembler : public AbstractAssembler { f_unorderedOrLessOrEqual = 14, f_ordered = 15, - // V8 coproc, pp 123 v8 manual - - cp_always = 8, - cp_never = 0, - cp_3 = 7, - cp_2 = 6, - cp_2or3 = 5, - cp_1 = 4, - cp_1or3 = 3, - cp_1or2 = 2, - cp_1or2or3 = 1, - cp_0 = 9, - cp_0or3 = 10, - cp_0or2 = 11, - cp_0or2or3 = 12, - cp_0or1 = 13, - cp_0or1or3 = 14, - cp_0or1or2 = 15, - - // for integers - never = 0, - equal = 1, - zero = 1, - lessEqual = 2, - less = 3, - lessEqualUnsigned = 4, - lessUnsigned = 5, - carrySet = 5, - negative = 6, - overflowSet = 7, - always = 8, - notEqual = 9, - notZero = 9, - greater = 10, - greaterEqual = 11, - greaterUnsigned = 12, - greaterEqualUnsigned = 13, - carryClear = 13, - positive = 14, - overflowClear = 15 + never = 0, + equal = 1, + zero = 1, + lessEqual = 2, + less = 3, + lessEqualUnsigned = 4, + lessUnsigned = 5, + carrySet = 5, + negative = 6, + overflowSet = 7, + always = 8, + notEqual = 9, + notZero = 9, + greater = 10, + greaterEqual = 11, + greaterUnsigned = 12, + greaterEqualUnsigned = 13, + carryClear = 13, + positive = 14, + overflowClear = 15 }; enum CC { - icc = 0, xcc = 2, // ptr_cc is the correct condition code for a pointer or intptr_t: - ptr_cc = NOT_LP64(icc) LP64_ONLY(xcc), - fcc0 = 0, fcc1 = 1, fcc2 = 2, fcc3 = 3 + icc = 0, xcc = 2, ptr_cc = xcc, + fcc0 = 0, fcc1 = 1, fcc2 = 2, fcc3 = 3 }; enum PrefetchFcn { - severalReads = 0, oneRead = 1, severalWritesAndPossiblyReads = 2, oneWrite = 3, page = 4 + severalReads = 0, oneRead = 1, severalWritesAndPossiblyReads = 2, oneWrite = 3, page = 4 }; public: @@ -354,7 +333,7 @@ class Assembler : public AbstractAssembler { return is_simm(d, nbits + 2); } - address target_distance(Label& L) { + address target_distance(Label &L) { // Assembler::target(L) should be called only when // a branch instruction is emitted since non-bound // labels record current pc() as a branch address. @@ -364,7 +343,7 @@ class Assembler : public AbstractAssembler { } // test if label is in simm16 range in words (wdisp16). - bool is_in_wdisp16_range(Label& L) { + bool is_in_wdisp16_range(Label &L) { return is_in_wdisp_range(target_distance(L), pc(), 16); } // test if the distance between two addresses fits in simm30 range in words @@ -392,41 +371,39 @@ class Assembler : public AbstractAssembler { // and be sign-extended. Check the range. static void assert_signed_range(intptr_t x, int nbits) { - assert(nbits == 32 || (-(1 << nbits-1) <= x && x < ( 1 << nbits-1)), + assert(nbits == 32 || (-(1 << nbits-1) <= x && x < (1 << nbits-1)), "value out of range: x=" INTPTR_FORMAT ", nbits=%d", x, nbits); } static void assert_signed_word_disp_range(intptr_t x, int nbits) { - assert( (x & 3) == 0, "not word aligned"); + assert((x & 3) == 0, "not word aligned"); assert_signed_range(x, nbits + 2); } static void assert_unsigned_const(int x, int nbits) { - assert( juint(x) < juint(1 << nbits), "unsigned constant out of range"); + assert(juint(x) < juint(1 << nbits), "unsigned constant out of range"); } - // fields: note bits numbered from LSB = 0, - // fields known by inclusive bit range + // fields: note bits numbered from LSB = 0, fields known by inclusive bit range static int fmask(juint hi_bit, juint lo_bit) { - assert( hi_bit >= lo_bit && 0 <= lo_bit && hi_bit < 32, "bad bits"); - return (1 << ( hi_bit-lo_bit + 1 )) - 1; + assert(hi_bit >= lo_bit && 0 <= lo_bit && hi_bit < 32, "bad bits"); + return (1 << (hi_bit-lo_bit + 1)) - 1; } // inverse of u_field static int inv_u_field(int x, int hi_bit, int lo_bit) { juint r = juint(x) >> lo_bit; - r &= fmask( hi_bit, lo_bit); + r &= fmask(hi_bit, lo_bit); return int(r); } - // signed version: extract from field and sign-extend static int inv_s_field(int x, int hi_bit, int lo_bit) { int sign_shift = 31 - hi_bit; - return inv_u_field( ((x << sign_shift) >> sign_shift), hi_bit, lo_bit); + return inv_u_field(((x << sign_shift) >> sign_shift), hi_bit, lo_bit); } // given a field that ranges from hi_bit to lo_bit (inclusive, @@ -435,72 +412,102 @@ class Assembler : public AbstractAssembler { #ifdef ASSERT static int u_field(int x, int hi_bit, int lo_bit) { - assert( ( x & ~fmask(hi_bit, lo_bit)) == 0, + assert((x & ~fmask(hi_bit, lo_bit)) == 0, "value out of range"); int r = x << lo_bit; - assert( inv_u_field(r, hi_bit, lo_bit) == x, "just checking"); + assert(inv_u_field(r, hi_bit, lo_bit) == x, "just checking"); return r; } #else // make sure this is inlined as it will reduce code size significantly - #define u_field(x, hi_bit, lo_bit) ((x) << (lo_bit)) + #define u_field(x, hi_bit, lo_bit) ((x) << (lo_bit)) #endif - static int inv_op( int x ) { return inv_u_field(x, 31, 30); } - static int inv_op2( int x ) { return inv_u_field(x, 24, 22); } - static int inv_op3( int x ) { return inv_u_field(x, 24, 19); } - static int inv_cond( int x ){ return inv_u_field(x, 28, 25); } + static int inv_op(int x) { return inv_u_field(x, 31, 30); } + static int inv_op2(int x) { return inv_u_field(x, 24, 22); } + static int inv_op3(int x) { return inv_u_field(x, 24, 19); } + static int inv_cond(int x) { return inv_u_field(x, 28, 25); } - static bool inv_immed( int x ) { return (x & Assembler::immed(true)) != 0; } + static bool inv_immed(int x) { return (x & Assembler::immed(true)) != 0; } - static Register inv_rd( int x ) { return as_Register(inv_u_field(x, 29, 25)); } - static Register inv_rs1( int x ) { return as_Register(inv_u_field(x, 18, 14)); } - static Register inv_rs2( int x ) { return as_Register(inv_u_field(x, 4, 0)); } + static Register inv_rd(int x) { return as_Register(inv_u_field(x, 29, 25)); } + static Register inv_rs1(int x) { return as_Register(inv_u_field(x, 18, 14)); } + static Register inv_rs2(int x) { return as_Register(inv_u_field(x, 4, 0)); } - static int op( int x) { return u_field(x, 31, 30); } - static int rd( Register r) { return u_field(r->encoding(), 29, 25); } - static int fcn( int x) { return u_field(x, 29, 25); } - static int op3( int x) { return u_field(x, 24, 19); } - static int rs1( Register r) { return u_field(r->encoding(), 18, 14); } - static int rs2( Register r) { return u_field(r->encoding(), 4, 0); } - static int annul( bool a) { return u_field(a ? 1 : 0, 29, 29); } - static int cond( int x) { return u_field(x, 28, 25); } - static int cond_mov( int x) { return u_field(x, 17, 14); } - static int rcond( RCondition x) { return u_field(x, 12, 10); } - static int op2( int x) { return u_field(x, 24, 22); } - static int predict( bool p) { return u_field(p ? 1 : 0, 19, 19); } - static int branchcc( CC fcca) { return u_field(fcca, 21, 20); } - static int cmpcc( CC fcca) { return u_field(fcca, 26, 25); } - static int imm_asi( int x) { return u_field(x, 12, 5); } - static int immed( bool i) { return u_field(i ? 1 : 0, 13, 13); } - static int opf_low6( int w) { return u_field(w, 10, 5); } - static int opf_low5( int w) { return u_field(w, 9, 5); } - static int op5( int x) { return u_field(x, 8, 5); } - static int trapcc( CC cc) { return u_field(cc, 12, 11); } - static int sx( int i) { return u_field(i, 12, 12); } // shift x=1 means 64-bit - static int opf( int x) { return u_field(x, 13, 5); } + static int op(int x) { return u_field(x, 31, 30); } + static int rd(Register r) { return u_field(r->encoding(), 29, 25); } + static int fcn(int x) { return u_field(x, 29, 25); } + static int op3(int x) { return u_field(x, 24, 19); } + static int rs1(Register r) { return u_field(r->encoding(), 18, 14); } + static int rs2(Register r) { return u_field(r->encoding(), 4, 0); } + static int annul(bool a) { return u_field(a ? 1 : 0, 29, 29); } + static int cond(int x) { return u_field(x, 28, 25); } + static int cond_mov(int x) { return u_field(x, 17, 14); } + static int rcond(RCondition x) { return u_field(x, 12, 10); } + static int op2(int x) { return u_field(x, 24, 22); } + static int predict(bool p) { return u_field(p ? 1 : 0, 19, 19); } + static int branchcc(CC fcca) { return u_field(fcca, 21, 20); } + static int cmpcc(CC fcca) { return u_field(fcca, 26, 25); } + static int imm_asi(int x) { return u_field(x, 12, 5); } + static int immed(bool i) { return u_field(i ? 1 : 0, 13, 13); } + static int opf_low6(int w) { return u_field(w, 10, 5); } + static int opf_low5(int w) { return u_field(w, 9, 5); } + static int op5(int x) { return u_field(x, 8, 5); } + static int trapcc(CC cc) { return u_field(cc, 12, 11); } + static int sx(int i) { return u_field(i, 12, 12); } // shift x=1 means 64-bit + static int opf(int x) { return u_field(x, 13, 5); } - static bool is_cbcond( int x ) { + static bool is_cbcond(int x) { return (VM_Version::has_cbcond() && (inv_cond(x) > rc_last) && inv_op(x) == branch_op && inv_op2(x) == bpr_op2); } - static bool is_cxb( int x ) { + static bool is_cxb(int x) { assert(is_cbcond(x), "wrong instruction"); - return (x & (1<<21)) != 0; + return (x & (1 << 21)) != 0; } - static int cond_cbcond( int x) { return u_field((((x & 8)<<1) + 8 + (x & 7)), 29, 25); } - static int inv_cond_cbcond(int x) { - assert(is_cbcond(x), "wrong instruction"); - return inv_u_field(x, 27, 25) | (inv_u_field(x, 29, 29)<<3); + static bool is_branch(int x) { + if (inv_op(x) != Assembler::branch_op) return false; + + bool is_bpr = inv_op2(x) == Assembler::bpr_op2; + bool is_bp = inv_op2(x) == Assembler::bp_op2; + bool is_br = inv_op2(x) == Assembler::br_op2; + bool is_fp = inv_op2(x) == Assembler::fb_op2; + bool is_fbp = inv_op2(x) == Assembler::fbp_op2; + + return is_bpr || is_bp || is_br || is_fp || is_fbp; + } + static bool is_call(int x) { + return inv_op(x) == Assembler::call_op; + } + static bool is_jump(int x) { + if (inv_op(x) != Assembler::arith_op) return false; + + bool is_jmpl = inv_op3(x) == Assembler::jmpl_op3; + bool is_rett = inv_op3(x) == Assembler::rett_op3; + + return is_jmpl || is_rett; + } + static bool is_rdpc(int x) { + return (inv_op(x) == Assembler::arith_op && inv_op3(x) == Assembler::rdreg_op3 && + inv_u_field(x, 18, 14) == 5); + } + static bool is_cti(int x) { + return is_branch(x) || is_call(x) || is_jump(x); // Ignoring done/retry } - static int opf_cc( CC c, bool useFloat ) { return u_field((useFloat ? 0 : 4) + c, 13, 11); } - static int mov_cc( CC c, bool useFloat ) { return u_field(useFloat ? 0 : 1, 18, 18) | u_field(c, 12, 11); } + static int cond_cbcond(int x) { return u_field((((x & 8) << 1) + 8 + (x & 7)), 29, 25); } + static int inv_cond_cbcond(int x) { + assert(is_cbcond(x), "wrong instruction"); + return inv_u_field(x, 27, 25) | (inv_u_field(x, 29, 29) << 3); + } - static int fd( FloatRegister r, FloatRegisterImpl::Width fwa) { return u_field(r->encoding(fwa), 29, 25); }; - static int fs1(FloatRegister r, FloatRegisterImpl::Width fwa) { return u_field(r->encoding(fwa), 18, 14); }; - static int fs2(FloatRegister r, FloatRegisterImpl::Width fwa) { return u_field(r->encoding(fwa), 4, 0); }; - static int fs3(FloatRegister r, FloatRegisterImpl::Width fwa) { return u_field(r->encoding(fwa), 13, 9); }; + static int opf_cc(CC c, bool useFloat) { return u_field((useFloat ? 0 : 4) + c, 13, 11); } + static int mov_cc(CC c, bool useFloat) { return u_field(useFloat ? 0 : 1, 18, 18) | u_field(c, 12, 11); } + + static int fd(FloatRegister r, FloatRegisterImpl::Width fwa) { return u_field(r->encoding(fwa), 29, 25); }; + static int fs1(FloatRegister r, FloatRegisterImpl::Width fwa) { return u_field(r->encoding(fwa), 18, 14); }; + static int fs2(FloatRegister r, FloatRegisterImpl::Width fwa) { return u_field(r->encoding(fwa), 4, 0); }; + static int fs3(FloatRegister r, FloatRegisterImpl::Width fwa) { return u_field(r->encoding(fwa), 13, 9); }; // some float instructions use this encoding on the op3 field static int alt_op3(int op, FloatRegisterImpl::Width w) { @@ -514,23 +521,22 @@ class Assembler : public AbstractAssembler { return op3(r); } - // compute inverse of simm static int inv_simm(int x, int nbits) { return (int)(x << (32 - nbits)) >> (32 - nbits); } - static int inv_simm13( int x ) { return inv_simm(x, 13); } + static int inv_simm13(int x) { return inv_simm(x, 13); } // signed immediate, in low bits, nbits long static int simm(int x, int nbits) { assert_signed_range(x, nbits); - return x & (( 1 << nbits ) - 1); + return x & ((1 << nbits) - 1); } // compute inverse of wdisp16 static intptr_t inv_wdisp16(int x, intptr_t pos) { - int lo = x & (( 1 << 14 ) - 1); + int lo = x & ((1 << 14) - 1); int hi = (x >> 20) & 3; if (hi >= 2) hi |= ~1; return (((hi << 14) | lo) << 2) + pos; @@ -540,9 +546,8 @@ class Assembler : public AbstractAssembler { static int wdisp16(intptr_t x, intptr_t off) { intptr_t xx = x - off; assert_signed_word_disp_range(xx, 16); - int r = (xx >> 2) & ((1 << 14) - 1) - | ( ( (xx>>(2+14)) & 3 ) << 20 ); - assert( inv_wdisp16(r, off) == x, "inverse is not inverse"); + int r = (xx >> 2) & ((1 << 14) - 1) | (((xx >> (2+14)) & 3) << 20); + assert(inv_wdisp16(r, off) == x, "inverse is not inverse"); return r; } @@ -560,260 +565,292 @@ class Assembler : public AbstractAssembler { assert(VM_Version::has_cbcond(), "This CPU does not have CBCOND instruction"); intptr_t xx = x - off; assert_signed_word_disp_range(xx, 10); - int r = ( ( (xx >> 2 ) & ((1 << 8) - 1) ) << 5 ) - | ( ( (xx >> (2+8)) & 3 ) << 19 ); + int r = (((xx >> 2) & ((1 << 8) - 1)) << 5) | (((xx >> (2+8)) & 3) << 19); // Have to fake cbcond instruction to pass assert in inv_wdisp10() - assert(inv_wdisp10((r | op(branch_op) | cond_cbcond(rc_last+1) | op2(bpr_op2)), off) == x, "inverse is not inverse"); + assert(inv_wdisp10((r | op(branch_op) | cond_cbcond(rc_last+1) | op2(bpr_op2)), off) == x, "inverse is not inverse"); return r; } // word displacement in low-order nbits bits - static intptr_t inv_wdisp( int x, intptr_t pos, int nbits ) { - int pre_sign_extend = x & (( 1 << nbits ) - 1); - int r = pre_sign_extend >= ( 1 << (nbits-1) ) - ? pre_sign_extend | ~(( 1 << nbits ) - 1) - : pre_sign_extend; + static intptr_t inv_wdisp(int x, intptr_t pos, int nbits) { + int pre_sign_extend = x & ((1 << nbits) - 1); + int r = (pre_sign_extend >= (1 << (nbits - 1)) ? + pre_sign_extend | ~((1 << nbits) - 1) : pre_sign_extend); return (r << 2) + pos; } - static int wdisp( intptr_t x, intptr_t off, int nbits ) { + static int wdisp(intptr_t x, intptr_t off, int nbits) { intptr_t xx = x - off; assert_signed_word_disp_range(xx, nbits); - int r = (xx >> 2) & (( 1 << nbits ) - 1); - assert( inv_wdisp( r, off, nbits ) == x, "inverse not inverse"); + int r = (xx >> 2) & ((1 << nbits) - 1); + assert(inv_wdisp(r, off, nbits) == x, "inverse not inverse"); return r; } // Extract the top 32 bits in a 64 bit word - static int32_t hi32( int64_t x ) { - int32_t r = int32_t( (uint64_t)x >> 32 ); + static int32_t hi32(int64_t x) { + int32_t r = int32_t((uint64_t)x >> 32); return r; } // given a sethi instruction, extract the constant, left-justified - static int inv_hi22( int x ) { + static int inv_hi22(int x) { return x << 10; } // create an imm22 field, given a 32-bit left-justified constant - static int hi22( int x ) { - int r = int( juint(x) >> 10 ); - assert( (r & ~((1 << 22) - 1)) == 0, "just checkin'"); + static int hi22(int x) { + int r = int(juint(x) >> 10); + assert((r & ~((1 << 22) - 1)) == 0, "just checkin'"); return r; } // create a low10 __value__ (not a field) for a given a 32-bit constant - static int low10( int x ) { + static int low10(int x) { return x & ((1 << 10) - 1); } // create a low12 __value__ (not a field) for a given a 32-bit constant - static int low12( int x ) { + static int low12(int x) { return x & ((1 << 12) - 1); } // AES crypto instructions supported only on certain processors - static void aes_only() { assert( VM_Version::has_aes(), "This instruction only works on SPARC with AES instructions support"); } + static void aes_only() { assert(VM_Version::has_aes(), "This instruction only works on SPARC with AES instructions support"); } // SHA crypto instructions supported only on certain processors - static void sha1_only() { assert( VM_Version::has_sha1(), "This instruction only works on SPARC with SHA1"); } - static void sha256_only() { assert( VM_Version::has_sha256(), "This instruction only works on SPARC with SHA256"); } - static void sha512_only() { assert( VM_Version::has_sha512(), "This instruction only works on SPARC with SHA512"); } + static void sha1_only() { assert(VM_Version::has_sha1(), "This instruction only works on SPARC with SHA1"); } + static void sha256_only() { assert(VM_Version::has_sha256(), "This instruction only works on SPARC with SHA256"); } + static void sha512_only() { assert(VM_Version::has_sha512(), "This instruction only works on SPARC with SHA512"); } // CRC32C instruction supported only on certain processors - static void crc32c_only() { assert( VM_Version::has_crc32c(), "This instruction only works on SPARC with CRC32C"); } + static void crc32c_only() { assert(VM_Version::has_crc32c(), "This instruction only works on SPARC with CRC32C"); } + + // FMAf instructions supported only on certain processors + static void fmaf_only() { assert(VM_Version::has_fmaf(), "This instruction only works on SPARC with FMAf"); } // instruction only in VIS1 - static void vis1_only() { assert( VM_Version::has_vis1(), "This instruction only works on SPARC with VIS1"); } + static void vis1_only() { assert(VM_Version::has_vis1(), "This instruction only works on SPARC with VIS1"); } // instruction only in VIS2 - static void vis2_only() { assert( VM_Version::has_vis2(), "This instruction only works on SPARC with VIS2"); } + static void vis2_only() { assert(VM_Version::has_vis2(), "This instruction only works on SPARC with VIS2"); } // instruction only in VIS3 - static void vis3_only() { assert( VM_Version::has_vis3(), "This instruction only works on SPARC with VIS3"); } - - // instruction only in v9 - static void v9_only() { } // do nothing + static void vis3_only() { assert(VM_Version::has_vis3(), "This instruction only works on SPARC with VIS3"); } // instruction deprecated in v9 - static void v9_dep() { } // do nothing for now - - // v8 has no CC field - static void v8_no_cc(CC cc) { if (cc) v9_only(); } + static void v9_dep() { } // do nothing for now protected: - // Simple delay-slot scheme: - // In order to check the programmer, the assembler keeps track of deley slots. - // It forbids CTIs in delay slots (conservative, but should be OK). - // Also, when putting an instruction into a delay slot, you must say - // asm->delayed()->add(...), in order to check that you don't omit - // delay-slot instructions. - // To implement this, we use a simple FSA - #ifdef ASSERT - #define CHECK_DELAY +#define VALIDATE_PIPELINE #endif -#ifdef CHECK_DELAY - enum Delay_state { no_delay, at_delay_slot, filling_delay_slot } delay_state; + +#ifdef VALIDATE_PIPELINE + // A simple delay-slot scheme: + // In order to check the programmer, the assembler keeps track of delay-slots. + // It forbids CTIs in delay-slots (conservative, but should be OK). Also, when + // emitting an instruction into a delay-slot, you must do so using delayed(), + // e.g. asm->delayed()->add(...), in order to check that you do not omit the + // delay-slot instruction. To implement this, we use a simple FSA. + enum { NoDelay, AtDelay, FillDelay } _delay_state; + + // A simple hazard scheme: + // In order to avoid pipeline stalls, due to single cycle pipeline hazards, we + // adopt a simplistic state tracking mechanism that will enforce an additional + // 'nop' instruction to be inserted prior to emitting an instruction that can + // expose a given hazard (currently, PC-related hazards only). + enum { NoHazard, PcHazard } _hazard_state; #endif public: - // Tells assembler next instruction must NOT be in delay slot. - // Use at start of multinstruction macros. + // Tell the assembler that the next instruction must NOT be in delay-slot. + // Use at start of multi-instruction macros. void assert_not_delayed() { - // This is a separate overloading to avoid creation of string constants - // in non-asserted code--with some compilers this pollutes the object code. -#ifdef CHECK_DELAY - assert_not_delayed("next instruction should not be a delay slot"); -#endif - } - void assert_not_delayed(const char* msg) { -#ifdef CHECK_DELAY - assert(delay_state == no_delay, msg); + // This is a separate entry to avoid the creation of string constants in + // non-asserted code, with some compilers this pollutes the object code. +#ifdef VALIDATE_PIPELINE + assert_no_delay("Next instruction should not be in a delay-slot."); #endif } protected: - // Insert a nop if the previous is cbcond - inline void insert_nop_after_cbcond(); + void assert_no_delay(const char* msg) { +#ifdef VALIDATE_PIPELINE + assert(_delay_state == NoDelay, msg); +#endif + } - // Delay slot helpers - // cti is called when emitting control-transfer instruction, - // BEFORE doing the emitting. - // Only effective when assertion-checking is enabled. + void assert_no_hazard() { +#ifdef VALIDATE_PIPELINE + assert(_hazard_state == NoHazard, "Unsolicited pipeline hazard."); +#endif + } + + private: + inline int32_t prev_insn() { + assert(offset() > 0, "Interface violation."); + int32_t* addr = (int32_t*)pc() - 1; + return *addr; + } + +#ifdef VALIDATE_PIPELINE + void validate_no_pipeline_hazards(); +#endif + + protected: + // Avoid possible pipeline stall by inserting an additional 'nop' instruction, + // if the previous instruction is a 'cbcond' or a 'rdpc'. + inline void avoid_pipeline_stall(); + + // A call to cti() is made before emitting a control-transfer instruction (CTI) + // in order to assert a CTI is not emitted right after a 'cbcond', nor in the + // delay-slot of another CTI. Only effective when assertions are enabled. void cti() { - // A cbcond instruction immediately followed by a CTI - // instruction introduces pipeline stalls, we need to avoid that. - no_cbcond_before(); -#ifdef CHECK_DELAY - assert_not_delayed("cti should not be in delay slot"); + // A 'cbcond' or 'rdpc' instruction immediately followed by a CTI introduces + // a pipeline stall, which we make sure to prohibit. + assert_no_cbcond_before(); + assert_no_rdpc_before(); +#ifdef VALIDATE_PIPELINE + assert_no_hazard(); + assert_no_delay("CTI in delay-slot."); #endif } - // called when emitting cti with a delay slot, AFTER emitting - void has_delay_slot() { -#ifdef CHECK_DELAY - assert_not_delayed("just checking"); - delay_state = at_delay_slot; + // Called when emitting CTI with a delay-slot, AFTER emitting. + inline void induce_delay_slot() { +#ifdef VALIDATE_PIPELINE + assert_no_delay("Already in delay-slot."); + _delay_state = AtDelay; #endif } - // cbcond instruction should not be generated one after an other - bool cbcond_before() { - if (offset() == 0) return false; // it is first instruction - int x = *(int*)(intptr_t(pc()) - 4); // previous instruction - return is_cbcond(x); + inline void induce_pc_hazard() { +#ifdef VALIDATE_PIPELINE + assert_no_hazard(); + _hazard_state = PcHazard; +#endif } - void no_cbcond_before() { - assert(offset() == 0 || !cbcond_before(), "cbcond should not follow an other cbcond"); - } -public: + bool is_cbcond_before() { return offset() > 0 ? is_cbcond(prev_insn()) : false; } - bool use_cbcond(Label& L) { - if (!UseCBCond || cbcond_before()) return false; + bool is_rdpc_before() { return offset() > 0 ? is_rdpc(prev_insn()) : false; } + + void assert_no_cbcond_before() { + assert(offset() == 0 || !is_cbcond_before(), "CBCOND should not be followed by CTI."); + } + + void assert_no_rdpc_before() { + assert(offset() == 0 || !is_rdpc_before(), "RDPC should not be followed by CTI."); + } + + public: + + bool use_cbcond(Label &L) { + if (!UseCBCond || is_cbcond_before()) return false; intptr_t x = intptr_t(target_distance(L)) - intptr_t(pc()); - assert( (x & 3) == 0, "not word aligned"); + assert((x & 3) == 0, "not word aligned"); return is_simm12(x); } // Tells assembler you know that next instruction is delayed Assembler* delayed() { -#ifdef CHECK_DELAY - assert ( delay_state == at_delay_slot, "delayed instruction is not in delay slot"); - delay_state = filling_delay_slot; +#ifdef VALIDATE_PIPELINE + assert(_delay_state == AtDelay, "Delayed instruction not in delay-slot."); + _delay_state = FillDelay; #endif return this; } void flush() { -#ifdef CHECK_DELAY - assert ( delay_state == no_delay, "ending code with a delay slot"); +#ifdef VALIDATE_PIPELINE + assert(_delay_state == NoDelay, "Ending code with a delay-slot."); + validate_no_pipeline_hazards(); #endif AbstractAssembler::flush(); } inline void emit_int32(int); // shadows AbstractAssembler::emit_int32 - inline void emit_data(int x); - inline void emit_data(int, RelocationHolder const&); + inline void emit_data(int); + inline void emit_data(int, RelocationHolder const &rspec); inline void emit_data(int, relocInfo::relocType rtype); - // helper for above fcns + // helper for above functions inline void check_delay(); public: // instructions, refer to page numbers in the SPARC Architecture Manual, V9 - // pp 135 (addc was addx in v8) + // pp 135 - inline void add(Register s1, Register s2, Register d ); - inline void add(Register s1, int simm13a, Register d ); + inline void add(Register s1, Register s2, Register d); + inline void add(Register s1, int simm13a, Register d); - inline void addcc( Register s1, Register s2, Register d ); - inline void addcc( Register s1, int simm13a, Register d ); - inline void addc( Register s1, Register s2, Register d ); - inline void addc( Register s1, int simm13a, Register d ); - inline void addccc( Register s1, Register s2, Register d ); - inline void addccc( Register s1, int simm13a, Register d ); + inline void addcc(Register s1, Register s2, Register d); + inline void addcc(Register s1, int simm13a, Register d); + inline void addc(Register s1, Register s2, Register d); + inline void addc(Register s1, int simm13a, Register d); + inline void addccc(Register s1, Register s2, Register d); + inline void addccc(Register s1, int simm13a, Register d); // 4-operand AES instructions - inline void aes_eround01( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ); - inline void aes_eround23( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ); - inline void aes_dround01( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ); - inline void aes_dround23( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ); - inline void aes_eround01_l( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ); - inline void aes_eround23_l( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ); - inline void aes_dround01_l( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ); - inline void aes_dround23_l( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ); - inline void aes_kexpand1( FloatRegister s1, FloatRegister s2, int imm5a, FloatRegister d ); + inline void aes_eround01(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d); + inline void aes_eround23(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d); + inline void aes_dround01(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d); + inline void aes_dround23(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d); + inline void aes_eround01_l(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d); + inline void aes_eround23_l(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d); + inline void aes_dround01_l(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d); + inline void aes_dround23_l(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d); + inline void aes_kexpand1(FloatRegister s1, FloatRegister s2, int imm5a, FloatRegister d); // 3-operand AES instructions - inline void aes_kexpand0( FloatRegister s1, FloatRegister s2, FloatRegister d ); - inline void aes_kexpand2( FloatRegister s1, FloatRegister s2, FloatRegister d ); + inline void aes_kexpand0(FloatRegister s1, FloatRegister s2, FloatRegister d); + inline void aes_kexpand2(FloatRegister s1, FloatRegister s2, FloatRegister d); // pp 136 inline void bpr(RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt = relocInfo::none); - inline void bpr(RCondition c, bool a, Predict p, Register s1, Label& L); + inline void bpr(RCondition c, bool a, Predict p, Register s1, Label &L); // compare and branch - inline void cbcond(Condition c, CC cc, Register s1, Register s2, Label& L); - inline void cbcond(Condition c, CC cc, Register s1, int simm5, Label& L); + inline void cbcond(Condition c, CC cc, Register s1, Register s2, Label &L); + inline void cbcond(Condition c, CC cc, Register s1, int simm5, Label &L); protected: // use MacroAssembler::br instead // pp 138 - inline void fb( Condition c, bool a, address d, relocInfo::relocType rt = relocInfo::none ); - inline void fb( Condition c, bool a, Label& L ); + inline void fb(Condition c, bool a, address d, relocInfo::relocType rt = relocInfo::none); + inline void fb(Condition c, bool a, Label &L); // pp 141 - inline void fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); - inline void fbp( Condition c, bool a, CC cc, Predict p, Label& L ); + inline void fbp(Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none); + inline void fbp(Condition c, bool a, CC cc, Predict p, Label &L); // pp 144 - inline void br( Condition c, bool a, address d, relocInfo::relocType rt = relocInfo::none ); - inline void br( Condition c, bool a, Label& L ); + inline void br(Condition c, bool a, address d, relocInfo::relocType rt = relocInfo::none); + inline void br(Condition c, bool a, Label &L); // pp 146 - inline void bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); - inline void bp( Condition c, bool a, CC cc, Predict p, Label& L ); + inline void bp(Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none); + inline void bp(Condition c, bool a, CC cc, Predict p, Label &L); // pp 149 - inline void call( address d, relocInfo::relocType rt = relocInfo::runtime_call_type ); - inline void call( Label& L, relocInfo::relocType rt = relocInfo::runtime_call_type ); + inline void call(address d, relocInfo::relocType rt = relocInfo::runtime_call_type); + inline void call(Label &L, relocInfo::relocType rt = relocInfo::runtime_call_type); - inline void call( address d, RelocationHolder const& rspec ); + inline void call(address d, RelocationHolder const &rspec); public: @@ -824,19 +861,19 @@ public: // at address s1 is swapped with the data in d. If the values are not equal, // the the contents of memory at s1 is loaded into d, without the swap. - inline void casa( Register s1, Register s2, Register d, int ia = -1 ); - inline void casxa( Register s1, Register s2, Register d, int ia = -1 ); + inline void casa(Register s1, Register s2, Register d, int ia = -1); + inline void casxa(Register s1, Register s2, Register d, int ia = -1); // pp 152 - inline void udiv( Register s1, Register s2, Register d ); - inline void udiv( Register s1, int simm13a, Register d ); - inline void sdiv( Register s1, Register s2, Register d ); - inline void sdiv( Register s1, int simm13a, Register d ); - inline void udivcc( Register s1, Register s2, Register d ); - inline void udivcc( Register s1, int simm13a, Register d ); - inline void sdivcc( Register s1, Register s2, Register d ); - inline void sdivcc( Register s1, int simm13a, Register d ); + inline void udiv(Register s1, Register s2, Register d); + inline void udiv(Register s1, int simm13a, Register d); + inline void sdiv(Register s1, Register s2, Register d); + inline void sdiv(Register s1, int simm13a, Register d); + inline void udivcc(Register s1, Register s2, Register d); + inline void udivcc(Register s1, int simm13a, Register d); + inline void sdivcc(Register s1, Register s2, Register d); + inline void sdivcc(Register s1, int simm13a, Register d); // pp 155 @@ -845,54 +882,58 @@ public: // pp 156 - inline void fadd( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ); - inline void fsub( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ); + inline void fadd(FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d); + inline void fsub(FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d); // pp 157 - inline void fcmp( FloatRegisterImpl::Width w, CC cc, FloatRegister s1, FloatRegister s2); - inline void fcmpe( FloatRegisterImpl::Width w, CC cc, FloatRegister s1, FloatRegister s2); + inline void fcmp(FloatRegisterImpl::Width w, CC cc, FloatRegister s1, FloatRegister s2); + inline void fcmpe(FloatRegisterImpl::Width w, CC cc, FloatRegister s1, FloatRegister s2); // pp 159 - inline void ftox( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ); - inline void ftoi( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ); + inline void ftox(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); + inline void ftoi(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); // pp 160 - inline void ftof( FloatRegisterImpl::Width sw, FloatRegisterImpl::Width dw, FloatRegister s, FloatRegister d ); + inline void ftof(FloatRegisterImpl::Width sw, FloatRegisterImpl::Width dw, FloatRegister s, FloatRegister d); // pp 161 - inline void fxtof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ); - inline void fitof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ); + inline void fxtof(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); + inline void fitof(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); // pp 162 - inline void fmov( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ); + inline void fmov(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); - inline void fneg( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ); + inline void fneg(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); - inline void fabs( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ); + inline void fabs(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); // pp 163 - inline void fmul( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ); - inline void fmul( FloatRegisterImpl::Width sw, FloatRegisterImpl::Width dw, FloatRegister s1, FloatRegister s2, FloatRegister d ); - inline void fdiv( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ); + inline void fmul(FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d); + inline void fmul(FloatRegisterImpl::Width sw, FloatRegisterImpl::Width dw, FloatRegister s1, FloatRegister s2, FloatRegister d); + inline void fdiv(FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d); // FXORs/FXORd instructions - inline void fxor( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ); + inline void fxor(FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d); // pp 164 - inline void fsqrt( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ); + inline void fsqrt(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d); + + // fmaf instructions. + + inline void fmadd(FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d); // pp 165 - inline void flush( Register s1, Register s2 ); - inline void flush( Register s1, int simm13a); + inline void flush(Register s1, Register s2); + inline void flush(Register s1, int simm13a); // pp 167 @@ -900,139 +941,140 @@ public: // pp 168 - void illtrap( int const22a); - // v8 unimp == illtrap(0) + void illtrap(int const22a); // pp 169 - void impdep1( int id1, int const19a ); - void impdep2( int id1, int const19a ); + void impdep1(int id1, int const19a); + void impdep2(int id1, int const19a); // pp 170 - void jmpl( Register s1, Register s2, Register d ); - void jmpl( Register s1, int simm13a, Register d, RelocationHolder const& rspec = RelocationHolder() ); + void jmpl(Register s1, Register s2, Register d); + void jmpl(Register s1, int simm13a, Register d, + RelocationHolder const &rspec = RelocationHolder()); // 171 inline void ldf(FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d); - inline void ldf(FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d, RelocationHolder const& rspec = RelocationHolder()); + inline void ldf(FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d, + RelocationHolder const &rspec = RelocationHolder()); - inline void ldfsr( Register s1, Register s2 ); - inline void ldfsr( Register s1, int simm13a); - inline void ldxfsr( Register s1, Register s2 ); - inline void ldxfsr( Register s1, int simm13a); + inline void ldfsr(Register s1, Register s2); + inline void ldfsr(Register s1, int simm13a); + inline void ldxfsr(Register s1, Register s2); + inline void ldxfsr(Register s1, int simm13a); // 173 - inline void ldfa( FloatRegisterImpl::Width w, Register s1, Register s2, int ia, FloatRegister d ); - inline void ldfa( FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d ); + inline void ldfa(FloatRegisterImpl::Width w, Register s1, Register s2, int ia, FloatRegister d); + inline void ldfa(FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d); - // pp 175, lduw is ld on v8 + // pp 175 - inline void ldsb( Register s1, Register s2, Register d ); - inline void ldsb( Register s1, int simm13a, Register d); - inline void ldsh( Register s1, Register s2, Register d ); - inline void ldsh( Register s1, int simm13a, Register d); - inline void ldsw( Register s1, Register s2, Register d ); - inline void ldsw( Register s1, int simm13a, Register d); - inline void ldub( Register s1, Register s2, Register d ); - inline void ldub( Register s1, int simm13a, Register d); - inline void lduh( Register s1, Register s2, Register d ); - inline void lduh( Register s1, int simm13a, Register d); - inline void lduw( Register s1, Register s2, Register d ); - inline void lduw( Register s1, int simm13a, Register d); - inline void ldx( Register s1, Register s2, Register d ); - inline void ldx( Register s1, int simm13a, Register d); - inline void ldd( Register s1, Register s2, Register d ); - inline void ldd( Register s1, int simm13a, Register d); + inline void ldsb(Register s1, Register s2, Register d); + inline void ldsb(Register s1, int simm13a, Register d); + inline void ldsh(Register s1, Register s2, Register d); + inline void ldsh(Register s1, int simm13a, Register d); + inline void ldsw(Register s1, Register s2, Register d); + inline void ldsw(Register s1, int simm13a, Register d); + inline void ldub(Register s1, Register s2, Register d); + inline void ldub(Register s1, int simm13a, Register d); + inline void lduh(Register s1, Register s2, Register d); + inline void lduh(Register s1, int simm13a, Register d); + inline void lduw(Register s1, Register s2, Register d); + inline void lduw(Register s1, int simm13a, Register d); + inline void ldx(Register s1, Register s2, Register d); + inline void ldx(Register s1, int simm13a, Register d); + inline void ldd(Register s1, Register s2, Register d); + inline void ldd(Register s1, int simm13a, Register d); // pp 177 - inline void ldsba( Register s1, Register s2, int ia, Register d ); - inline void ldsba( Register s1, int simm13a, Register d ); - inline void ldsha( Register s1, Register s2, int ia, Register d ); - inline void ldsha( Register s1, int simm13a, Register d ); - inline void ldswa( Register s1, Register s2, int ia, Register d ); - inline void ldswa( Register s1, int simm13a, Register d ); - inline void lduba( Register s1, Register s2, int ia, Register d ); - inline void lduba( Register s1, int simm13a, Register d ); - inline void lduha( Register s1, Register s2, int ia, Register d ); - inline void lduha( Register s1, int simm13a, Register d ); - inline void lduwa( Register s1, Register s2, int ia, Register d ); - inline void lduwa( Register s1, int simm13a, Register d ); - inline void ldxa( Register s1, Register s2, int ia, Register d ); - inline void ldxa( Register s1, int simm13a, Register d ); + inline void ldsba(Register s1, Register s2, int ia, Register d); + inline void ldsba(Register s1, int simm13a, Register d); + inline void ldsha(Register s1, Register s2, int ia, Register d); + inline void ldsha(Register s1, int simm13a, Register d); + inline void ldswa(Register s1, Register s2, int ia, Register d); + inline void ldswa(Register s1, int simm13a, Register d); + inline void lduba(Register s1, Register s2, int ia, Register d); + inline void lduba(Register s1, int simm13a, Register d); + inline void lduha(Register s1, Register s2, int ia, Register d); + inline void lduha(Register s1, int simm13a, Register d); + inline void lduwa(Register s1, Register s2, int ia, Register d); + inline void lduwa(Register s1, int simm13a, Register d); + inline void ldxa(Register s1, Register s2, int ia, Register d); + inline void ldxa(Register s1, int simm13a, Register d); // pp 181 - inline void and3( Register s1, Register s2, Register d ); - inline void and3( Register s1, int simm13a, Register d ); - inline void andcc( Register s1, Register s2, Register d ); - inline void andcc( Register s1, int simm13a, Register d ); - inline void andn( Register s1, Register s2, Register d ); - inline void andn( Register s1, int simm13a, Register d ); - inline void andncc( Register s1, Register s2, Register d ); - inline void andncc( Register s1, int simm13a, Register d ); - inline void or3( Register s1, Register s2, Register d ); - inline void or3( Register s1, int simm13a, Register d ); - inline void orcc( Register s1, Register s2, Register d ); - inline void orcc( Register s1, int simm13a, Register d ); - inline void orn( Register s1, Register s2, Register d ); - inline void orn( Register s1, int simm13a, Register d ); - inline void orncc( Register s1, Register s2, Register d ); - inline void orncc( Register s1, int simm13a, Register d ); - inline void xor3( Register s1, Register s2, Register d ); - inline void xor3( Register s1, int simm13a, Register d ); - inline void xorcc( Register s1, Register s2, Register d ); - inline void xorcc( Register s1, int simm13a, Register d ); - inline void xnor( Register s1, Register s2, Register d ); - inline void xnor( Register s1, int simm13a, Register d ); - inline void xnorcc( Register s1, Register s2, Register d ); - inline void xnorcc( Register s1, int simm13a, Register d ); + inline void and3(Register s1, Register s2, Register d); + inline void and3(Register s1, int simm13a, Register d); + inline void andcc(Register s1, Register s2, Register d); + inline void andcc(Register s1, int simm13a, Register d); + inline void andn(Register s1, Register s2, Register d); + inline void andn(Register s1, int simm13a, Register d); + inline void andncc(Register s1, Register s2, Register d); + inline void andncc(Register s1, int simm13a, Register d); + inline void or3(Register s1, Register s2, Register d); + inline void or3(Register s1, int simm13a, Register d); + inline void orcc(Register s1, Register s2, Register d); + inline void orcc(Register s1, int simm13a, Register d); + inline void orn(Register s1, Register s2, Register d); + inline void orn(Register s1, int simm13a, Register d); + inline void orncc(Register s1, Register s2, Register d); + inline void orncc(Register s1, int simm13a, Register d); + inline void xor3(Register s1, Register s2, Register d); + inline void xor3(Register s1, int simm13a, Register d); + inline void xorcc(Register s1, Register s2, Register d); + inline void xorcc(Register s1, int simm13a, Register d); + inline void xnor(Register s1, Register s2, Register d); + inline void xnor(Register s1, int simm13a, Register d); + inline void xnorcc(Register s1, Register s2, Register d); + inline void xnorcc(Register s1, int simm13a, Register d); // pp 183 - inline void membar( Membar_mask_bits const7a ); + inline void membar(Membar_mask_bits const7a); // pp 185 - inline void fmov( FloatRegisterImpl::Width w, Condition c, bool floatCC, CC cca, FloatRegister s2, FloatRegister d ); + inline void fmov(FloatRegisterImpl::Width w, Condition c, bool floatCC, CC cca, FloatRegister s2, FloatRegister d); // pp 189 - inline void fmov( FloatRegisterImpl::Width w, RCondition c, Register s1, FloatRegister s2, FloatRegister d ); + inline void fmov(FloatRegisterImpl::Width w, RCondition c, Register s1, FloatRegister s2, FloatRegister d); // pp 191 - inline void movcc( Condition c, bool floatCC, CC cca, Register s2, Register d ); - inline void movcc( Condition c, bool floatCC, CC cca, int simm11a, Register d ); + inline void movcc(Condition c, bool floatCC, CC cca, Register s2, Register d); + inline void movcc(Condition c, bool floatCC, CC cca, int simm11a, Register d); // pp 195 - inline void movr( RCondition c, Register s1, Register s2, Register d ); - inline void movr( RCondition c, Register s1, int simm10a, Register d ); + inline void movr(RCondition c, Register s1, Register s2, Register d); + inline void movr(RCondition c, Register s1, int simm10a, Register d); // pp 196 - inline void mulx( Register s1, Register s2, Register d ); - inline void mulx( Register s1, int simm13a, Register d ); - inline void sdivx( Register s1, Register s2, Register d ); - inline void sdivx( Register s1, int simm13a, Register d ); - inline void udivx( Register s1, Register s2, Register d ); - inline void udivx( Register s1, int simm13a, Register d ); + inline void mulx(Register s1, Register s2, Register d); + inline void mulx(Register s1, int simm13a, Register d); + inline void sdivx(Register s1, Register s2, Register d); + inline void sdivx(Register s1, int simm13a, Register d); + inline void udivx(Register s1, Register s2, Register d); + inline void udivx(Register s1, int simm13a, Register d); // pp 197 - inline void umul( Register s1, Register s2, Register d ); - inline void umul( Register s1, int simm13a, Register d ); - inline void smul( Register s1, Register s2, Register d ); - inline void smul( Register s1, int simm13a, Register d ); - inline void umulcc( Register s1, Register s2, Register d ); - inline void umulcc( Register s1, int simm13a, Register d ); - inline void smulcc( Register s1, Register s2, Register d ); - inline void smulcc( Register s1, int simm13a, Register d ); + inline void umul(Register s1, Register s2, Register d); + inline void umul(Register s1, int simm13a, Register d); + inline void smul(Register s1, Register s2, Register d); + inline void smul(Register s1, int simm13a, Register d); + inline void umulcc(Register s1, Register s2, Register d); + inline void umulcc(Register s1, int simm13a, Register d); + inline void smulcc(Register s1, Register s2, Register d); + inline void smulcc(Register s1, int simm13a, Register d); // pp 201 @@ -1042,40 +1084,40 @@ public: // pp 202 - inline void popc( Register s, Register d); - inline void popc( int simm13a, Register d); + inline void popc(Register s, Register d); + inline void popc(int simm13a, Register d); // pp 203 - inline void prefetch( Register s1, Register s2, PrefetchFcn f); - inline void prefetch( Register s1, int simm13a, PrefetchFcn f); + inline void prefetch(Register s1, Register s2, PrefetchFcn f); + inline void prefetch(Register s1, int simm13a, PrefetchFcn f); - inline void prefetcha( Register s1, Register s2, int ia, PrefetchFcn f ); - inline void prefetcha( Register s1, int simm13a, PrefetchFcn f ); + inline void prefetcha(Register s1, Register s2, int ia, PrefetchFcn f); + inline void prefetcha(Register s1, int simm13a, PrefetchFcn f); // pp 208 // not implementing read privileged register - inline void rdy( Register d); - inline void rdccr( Register d); - inline void rdasi( Register d); - inline void rdtick( Register d); - inline void rdpc( Register d); - inline void rdfprs( Register d); + inline void rdy(Register d); + inline void rdccr(Register d); + inline void rdasi(Register d); + inline void rdtick(Register d); + inline void rdpc(Register d); + inline void rdfprs(Register d); // pp 213 - inline void rett( Register s1, Register s2); - inline void rett( Register s1, int simm13a, relocInfo::relocType rt = relocInfo::none); + inline void rett(Register s1, Register s2); + inline void rett(Register s1, int simm13a, relocInfo::relocType rt = relocInfo::none); // pp 214 - inline void save( Register s1, Register s2, Register d ); - inline void save( Register s1, int simm13a, Register d ); + inline void save(Register s1, Register s2, Register d); + inline void save(Register s1, int simm13a, Register d); - inline void restore( Register s1 = G0, Register s2 = G0, Register d = G0 ); - inline void restore( Register s1, int simm13a, Register d ); + inline void restore(Register s1 = G0, Register s2 = G0, Register d = G0); + inline void restore(Register s1, int simm13a, Register d); // pp 216 @@ -1084,26 +1126,27 @@ public: // pp 217 - inline void sethi( int imm22a, Register d, RelocationHolder const& rspec = RelocationHolder() ); + inline void sethi(int imm22a, Register d, RelocationHolder const &rspec = RelocationHolder()); + // pp 218 - inline void sll( Register s1, Register s2, Register d ); - inline void sll( Register s1, int imm5a, Register d ); - inline void srl( Register s1, Register s2, Register d ); - inline void srl( Register s1, int imm5a, Register d ); - inline void sra( Register s1, Register s2, Register d ); - inline void sra( Register s1, int imm5a, Register d ); + inline void sll(Register s1, Register s2, Register d); + inline void sll(Register s1, int imm5a, Register d); + inline void srl(Register s1, Register s2, Register d); + inline void srl(Register s1, int imm5a, Register d); + inline void sra(Register s1, Register s2, Register d); + inline void sra(Register s1, int imm5a, Register d); - inline void sllx( Register s1, Register s2, Register d ); - inline void sllx( Register s1, int imm6a, Register d ); - inline void srlx( Register s1, Register s2, Register d ); - inline void srlx( Register s1, int imm6a, Register d ); - inline void srax( Register s1, Register s2, Register d ); - inline void srax( Register s1, int imm6a, Register d ); + inline void sllx(Register s1, Register s2, Register d); + inline void sllx(Register s1, int imm6a, Register d); + inline void srlx(Register s1, Register s2, Register d); + inline void srlx(Register s1, int imm6a, Register d); + inline void srax(Register s1, Register s2, Register d); + inline void srax(Register s1, int imm6a, Register d); // pp 220 - inline void sir( int simm13a ); + inline void sir(int simm13a); // pp 221 @@ -1111,125 +1154,125 @@ public: // pp 222 - inline void stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2); - inline void stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a); + inline void stf(FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2); + inline void stf(FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a); - inline void stfsr( Register s1, Register s2 ); - inline void stfsr( Register s1, int simm13a); - inline void stxfsr( Register s1, Register s2 ); - inline void stxfsr( Register s1, int simm13a); + inline void stfsr(Register s1, Register s2); + inline void stfsr(Register s1, int simm13a); + inline void stxfsr(Register s1, Register s2); + inline void stxfsr(Register s1, int simm13a); - // pp 224 + // pp 224 - inline void stfa( FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2, int ia ); - inline void stfa( FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a ); + inline void stfa(FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2, int ia); + inline void stfa(FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a); - // p 226 + // pp 226 - inline void stb( Register d, Register s1, Register s2 ); - inline void stb( Register d, Register s1, int simm13a); - inline void sth( Register d, Register s1, Register s2 ); - inline void sth( Register d, Register s1, int simm13a); - inline void stw( Register d, Register s1, Register s2 ); - inline void stw( Register d, Register s1, int simm13a); - inline void stx( Register d, Register s1, Register s2 ); - inline void stx( Register d, Register s1, int simm13a); - inline void std( Register d, Register s1, Register s2 ); - inline void std( Register d, Register s1, int simm13a); + inline void stb(Register d, Register s1, Register s2); + inline void stb(Register d, Register s1, int simm13a); + inline void sth(Register d, Register s1, Register s2); + inline void sth(Register d, Register s1, int simm13a); + inline void stw(Register d, Register s1, Register s2); + inline void stw(Register d, Register s1, int simm13a); + inline void stx(Register d, Register s1, Register s2); + inline void stx(Register d, Register s1, int simm13a); + inline void std(Register d, Register s1, Register s2); + inline void std(Register d, Register s1, int simm13a); // pp 177 - inline void stba( Register d, Register s1, Register s2, int ia ); - inline void stba( Register d, Register s1, int simm13a ); - inline void stha( Register d, Register s1, Register s2, int ia ); - inline void stha( Register d, Register s1, int simm13a ); - inline void stwa( Register d, Register s1, Register s2, int ia ); - inline void stwa( Register d, Register s1, int simm13a ); - inline void stxa( Register d, Register s1, Register s2, int ia ); - inline void stxa( Register d, Register s1, int simm13a ); - inline void stda( Register d, Register s1, Register s2, int ia ); - inline void stda( Register d, Register s1, int simm13a ); + inline void stba(Register d, Register s1, Register s2, int ia); + inline void stba(Register d, Register s1, int simm13a); + inline void stha(Register d, Register s1, Register s2, int ia); + inline void stha(Register d, Register s1, int simm13a); + inline void stwa(Register d, Register s1, Register s2, int ia); + inline void stwa(Register d, Register s1, int simm13a); + inline void stxa(Register d, Register s1, Register s2, int ia); + inline void stxa(Register d, Register s1, int simm13a); + inline void stda(Register d, Register s1, Register s2, int ia); + inline void stda(Register d, Register s1, int simm13a); // pp 230 - inline void sub( Register s1, Register s2, Register d ); - inline void sub( Register s1, int simm13a, Register d ); + inline void sub(Register s1, Register s2, Register d); + inline void sub(Register s1, int simm13a, Register d); - inline void subcc( Register s1, Register s2, Register d ); - inline void subcc( Register s1, int simm13a, Register d ); - inline void subc( Register s1, Register s2, Register d ); - inline void subc( Register s1, int simm13a, Register d ); - inline void subccc( Register s1, Register s2, Register d ); - inline void subccc( Register s1, int simm13a, Register d ); + inline void subcc(Register s1, Register s2, Register d); + inline void subcc(Register s1, int simm13a, Register d); + inline void subc(Register s1, Register s2, Register d); + inline void subc(Register s1, int simm13a, Register d); + inline void subccc(Register s1, Register s2, Register d); + inline void subccc(Register s1, int simm13a, Register d); // pp 231 - inline void swap( Register s1, Register s2, Register d ); - inline void swap( Register s1, int simm13a, Register d); + inline void swap(Register s1, Register s2, Register d); + inline void swap(Register s1, int simm13a, Register d); // pp 232 - inline void swapa( Register s1, Register s2, int ia, Register d ); - inline void swapa( Register s1, int simm13a, Register d ); + inline void swapa(Register s1, Register s2, int ia, Register d); + inline void swapa(Register s1, int simm13a, Register d); // pp 234, note op in book is wrong, see pp 268 - inline void taddcc( Register s1, Register s2, Register d ); - inline void taddcc( Register s1, int simm13a, Register d ); + inline void taddcc(Register s1, Register s2, Register d); + inline void taddcc(Register s1, int simm13a, Register d); // pp 235 - inline void tsubcc( Register s1, Register s2, Register d ); - inline void tsubcc( Register s1, int simm13a, Register d ); + inline void tsubcc(Register s1, Register s2, Register d); + inline void tsubcc(Register s1, int simm13a, Register d); // pp 237 - inline void trap( Condition c, CC cc, Register s1, Register s2 ); - inline void trap( Condition c, CC cc, Register s1, int trapa ); + inline void trap(Condition c, CC cc, Register s1, Register s2); + inline void trap(Condition c, CC cc, Register s1, int trapa); // simple uncond. trap - inline void trap( int trapa ); + inline void trap(int trapa); // pp 239 omit write priv register for now - inline void wry( Register d); + inline void wry(Register d); inline void wrccr(Register s); inline void wrccr(Register s, int simm13a); inline void wrasi(Register d); // wrasi(d, imm) stores (d xor imm) to asi inline void wrasi(Register d, int simm13a); - inline void wrfprs( Register d); + inline void wrfprs(Register d); - // VIS1 instructions + // VIS1 instructions - inline void alignaddr( Register s1, Register s2, Register d ); + inline void alignaddr(Register s1, Register s2, Register d); - inline void faligndata( FloatRegister s1, FloatRegister s2, FloatRegister d ); + inline void faligndata(FloatRegister s1, FloatRegister s2, FloatRegister d); - inline void fzero( FloatRegisterImpl::Width w, FloatRegister d ); + inline void fzero(FloatRegisterImpl::Width w, FloatRegister d); - inline void fsrc2( FloatRegisterImpl::Width w, FloatRegister s2, FloatRegister d ); + inline void fsrc2(FloatRegisterImpl::Width w, FloatRegister s2, FloatRegister d); - inline void fnot1( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister d ); + inline void fnot1(FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister d); - inline void fpmerge( FloatRegister s1, FloatRegister s2, FloatRegister d ); + inline void fpmerge(FloatRegister s1, FloatRegister s2, FloatRegister d); - inline void stpartialf( Register s1, Register s2, FloatRegister d, int ia = -1 ); + inline void stpartialf(Register s1, Register s2, FloatRegister d, int ia = -1); - // VIS2 instructions + // VIS2 instructions - inline void edge8n( Register s1, Register s2, Register d ); + inline void edge8n(Register s1, Register s2, Register d); - inline void bmask( Register s1, Register s2, Register d ); - inline void bshuffle( FloatRegister s1, FloatRegister s2, FloatRegister d ); + inline void bmask(Register s1, Register s2, Register d); + inline void bshuffle(FloatRegister s1, FloatRegister s2, FloatRegister d); // VIS3 instructions - inline void movstosw( FloatRegister s, Register d ); - inline void movstouw( FloatRegister s, Register d ); - inline void movdtox( FloatRegister s, Register d ); + inline void movstosw(FloatRegister s, Register d); + inline void movstouw(FloatRegister s, Register d); + inline void movdtox(FloatRegister s, Register d); - inline void movwtos( Register s, FloatRegister d ); - inline void movxtod( Register s, FloatRegister d ); + inline void movwtos(Register s, FloatRegister d); + inline void movxtod(Register s, FloatRegister d); inline void xmulx(Register s1, Register s2, Register d); inline void xmulxhi(Register s1, Register s2, Register d); @@ -1242,12 +1285,13 @@ public: // CRC32C instruction - inline void crc32c( FloatRegister s1, FloatRegister s2, FloatRegister d ); + inline void crc32c(FloatRegister s1, FloatRegister s2, FloatRegister d); // Creation Assembler(CodeBuffer* code) : AbstractAssembler(code) { -#ifdef CHECK_DELAY - delay_state = no_delay; +#ifdef VALIDATE_PIPELINE + _delay_state = NoDelay; + _hazard_state = NoHazard; #endif } }; diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp index c18b07ec019..070a1f80db3 100644 --- a/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp +++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -28,21 +28,42 @@ #include "asm/assembler.hpp" -inline void Assembler::insert_nop_after_cbcond() { - if (UseCBCond && cbcond_before()) { +inline void Assembler::avoid_pipeline_stall() { +#ifdef VALIDATE_PIPELINE + if (_hazard_state == PcHazard) { + assert(is_cbcond_before() || is_rdpc_before(), "PC-hazard not preceeded by CBCOND or RDPC."); + assert_no_delay("Must not have PC-hazard state in delay-slot."); nop(); + _hazard_state = NoHazard; + } +#endif + + bool post_cond = is_cbcond_before(); + bool post_rdpc = is_rdpc_before(); + + if (post_cond || post_rdpc) { + nop(); +#ifdef VALIDATE_PIPELINE + if (_hazard_state != PcHazard) { + assert(post_cond, "CBCOND before when no hazard @0x%p\n", pc()); + assert(post_rdpc, "RDPC before when no hazard @0x%p\n", pc()); + } +#endif } } inline void Assembler::check_delay() { -# ifdef CHECK_DELAY - guarantee( delay_state != at_delay_slot, "must say delayed() when filling delay slot"); - delay_state = no_delay; -# endif +#ifdef VALIDATE_PIPELINE + guarantee(_delay_state != AtDelay, "Use delayed() when filling delay-slot"); + _delay_state = NoDelay; +#endif } inline void Assembler::emit_int32(int x) { check_delay(); +#ifdef VALIDATE_PIPELINE + _hazard_state = NoHazard; +#endif AbstractAssembler::emit_int32(x); } @@ -55,394 +76,1024 @@ inline void Assembler::emit_data(int x, relocInfo::relocType rtype) { emit_int32(x); } -inline void Assembler::emit_data(int x, RelocationHolder const& rspec) { +inline void Assembler::emit_data(int x, RelocationHolder const &rspec) { relocate(rspec); emit_int32(x); } -inline void Assembler::add(Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::add(Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } +inline void Assembler::add(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::add(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} -inline void Assembler::addcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::addcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::addc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(addc_op3 ) | rs1(s1) | rs2(s2) ); } -inline void Assembler::addc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(addc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::addccc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(addc_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::addccc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(addc_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } - -inline void Assembler::aes_eround01( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ) { aes_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_eround01_op5) | fs2(s2, FloatRegisterImpl::D) ); } -inline void Assembler::aes_eround23( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ) { aes_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_eround23_op5) | fs2(s2, FloatRegisterImpl::D) ); } -inline void Assembler::aes_dround01( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ) { aes_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_dround01_op5) | fs2(s2, FloatRegisterImpl::D) ); } -inline void Assembler::aes_dround23( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ) { aes_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_dround23_op5) | fs2(s2, FloatRegisterImpl::D) ); } -inline void Assembler::aes_eround01_l( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ) { aes_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_eround01_l_op5) | fs2(s2, FloatRegisterImpl::D) ); } -inline void Assembler::aes_eround23_l( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ) { aes_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_eround23_l_op5) | fs2(s2, FloatRegisterImpl::D) ); } -inline void Assembler::aes_dround01_l( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ) { aes_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_dround01_l_op5) | fs2(s2, FloatRegisterImpl::D) ); } -inline void Assembler::aes_dround23_l( FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d ) { aes_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_dround23_l_op5) | fs2(s2, FloatRegisterImpl::D) ); } -inline void Assembler::aes_kexpand1( FloatRegister s1, FloatRegister s2, int imm5a, FloatRegister d ) { aes_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | u_field(imm5a, 13, 9) | op5(aes_kexpand1_op5) | fs2(s2, FloatRegisterImpl::D) ); } +inline void Assembler::addcc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::addcc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(add_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::addc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(addc_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::addc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(addc_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::addccc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(addc_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::addccc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(addc_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::aes_eround01(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d) { + aes_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_eround01_op5) | fs2(s2, FloatRegisterImpl::D)); +} +inline void Assembler::aes_eround23(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d) { + aes_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_eround23_op5) | fs2(s2, FloatRegisterImpl::D)); +} +inline void Assembler::aes_dround01(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d) { + aes_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_dround01_op5) | fs2(s2, FloatRegisterImpl::D)); +} +inline void Assembler::aes_dround23(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d) { + aes_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_dround23_op5) | fs2(s2, FloatRegisterImpl::D)); +} +inline void Assembler::aes_eround01_l(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d) { + aes_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_eround01_l_op5) | fs2(s2, FloatRegisterImpl::D)); +} +inline void Assembler::aes_eround23_l(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d) { + aes_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_eround23_l_op5) | fs2(s2, FloatRegisterImpl::D)); +} +inline void Assembler::aes_dround01_l(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d) { + aes_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_dround01_l_op5) | fs2(s2, FloatRegisterImpl::D)); +} +inline void Assembler::aes_dround23_l(FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d) { + aes_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | fs3(s3, FloatRegisterImpl::D) | op5(aes_dround23_l_op5) | fs2(s2, FloatRegisterImpl::D)); +} +inline void Assembler::aes_kexpand1(FloatRegister s1, FloatRegister s2, int imm5a, FloatRegister d) { + aes_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes4_op3) | fs1(s1, FloatRegisterImpl::D) | u_field(imm5a, 13, 9) | op5(aes_kexpand1_op5) | fs2(s2, FloatRegisterImpl::D)); +} // 3-operand AES instructions -inline void Assembler::aes_kexpand0( FloatRegister s1, FloatRegister s2, FloatRegister d ) { aes_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes3_op3) | fs1(s1, FloatRegisterImpl::D) | opf(aes_kexpand0_opf) | fs2(s2, FloatRegisterImpl::D) ); } -inline void Assembler::aes_kexpand2( FloatRegister s1, FloatRegister s2, FloatRegister d ) { aes_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes3_op3) | fs1(s1, FloatRegisterImpl::D) | opf(aes_kexpand2_opf) | fs2(s2, FloatRegisterImpl::D) ); } - -inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt ) { v9_only(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bpr_op2) | wdisp16(intptr_t(d), intptr_t(pc())) | predict(p) | rs1(s1), rt); has_delay_slot(); } -inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, Label& L) { insert_nop_after_cbcond(); bpr( c, a, p, s1, target(L)); } - -inline void Assembler::fb( Condition c, bool a, address d, relocInfo::relocType rt ) { v9_dep(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(fb_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); has_delay_slot(); } -inline void Assembler::fb( Condition c, bool a, Label& L ) { insert_nop_after_cbcond(); fb(c, a, target(L)); } - -inline void Assembler::fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { v9_only(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(fbp_op2) | branchcc(cc) | predict(p) | wdisp(intptr_t(d), intptr_t(pc()), 19), rt); has_delay_slot(); } -inline void Assembler::fbp( Condition c, bool a, CC cc, Predict p, Label& L ) { insert_nop_after_cbcond(); fbp(c, a, cc, p, target(L)); } - -inline void Assembler::br( Condition c, bool a, address d, relocInfo::relocType rt ) { v9_dep(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(br_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); has_delay_slot(); } -inline void Assembler::br( Condition c, bool a, Label& L ) { insert_nop_after_cbcond(); br(c, a, target(L)); } - -inline void Assembler::bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { v9_only(); insert_nop_after_cbcond(); cti(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bp_op2) | branchcc(cc) | predict(p) | wdisp(intptr_t(d), intptr_t(pc()), 19), rt); has_delay_slot(); } -inline void Assembler::bp( Condition c, bool a, CC cc, Predict p, Label& L ) { insert_nop_after_cbcond(); bp(c, a, cc, p, target(L)); } - -// compare and branch -inline void Assembler::cbcond(Condition c, CC cc, Register s1, Register s2, Label& L) { cti(); no_cbcond_before(); emit_data(op(branch_op) | cond_cbcond(c) | op2(bpr_op2) | branchcc(cc) | wdisp10(intptr_t(target(L)), intptr_t(pc())) | rs1(s1) | rs2(s2)); } -inline void Assembler::cbcond(Condition c, CC cc, Register s1, int simm5, Label& L) { cti(); no_cbcond_before(); emit_data(op(branch_op) | cond_cbcond(c) | op2(bpr_op2) | branchcc(cc) | wdisp10(intptr_t(target(L)), intptr_t(pc())) | rs1(s1) | immed(true) | simm(simm5, 5)); } - -inline void Assembler::call( address d, relocInfo::relocType rt ) { insert_nop_after_cbcond(); cti(); emit_data( op(call_op) | wdisp(intptr_t(d), intptr_t(pc()), 30), rt); has_delay_slot(); assert(rt != relocInfo::virtual_call_type, "must use virtual_call_Relocation::spec"); } -inline void Assembler::call( Label& L, relocInfo::relocType rt ) { insert_nop_after_cbcond(); call( target(L), rt); } - -inline void Assembler::call( address d, RelocationHolder const& rspec ) { insert_nop_after_cbcond(); cti(); emit_data( op(call_op) | wdisp(intptr_t(d), intptr_t(pc()), 30), rspec); has_delay_slot(); assert(rspec.type() != relocInfo::virtual_call_type, "must use virtual_call_Relocation::spec"); } - -inline void Assembler::casa( Register s1, Register s2, Register d, int ia ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(casa_op3 ) | rs1(s1) | (ia == -1 ? immed(true) : imm_asi(ia)) | rs2(s2)); } -inline void Assembler::casxa( Register s1, Register s2, Register d, int ia ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(casxa_op3) | rs1(s1) | (ia == -1 ? immed(true) : imm_asi(ia)) | rs2(s2)); } - -inline void Assembler::udiv( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(udiv_op3 ) | rs1(s1) | rs2(s2)); } -inline void Assembler::udiv( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(udiv_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::sdiv( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sdiv_op3 ) | rs1(s1) | rs2(s2)); } -inline void Assembler::sdiv( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sdiv_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::udivcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(udiv_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); } -inline void Assembler::udivcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(udiv_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::sdivcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sdiv_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); } -inline void Assembler::sdivcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sdiv_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } - -inline void Assembler::done() { v9_only(); cti(); emit_int32( op(arith_op) | fcn(0) | op3(done_op3) ); } -inline void Assembler::retry() { v9_only(); cti(); emit_int32( op(arith_op) | fcn(1) | op3(retry_op3) ); } - -inline void Assembler::fadd( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x40 + w) | fs2(s2, w)); } -inline void Assembler::fsub( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x44 + w) | fs2(s2, w)); } - -inline void Assembler::fcmp( FloatRegisterImpl::Width w, CC cc, FloatRegister s1, FloatRegister s2) { emit_int32( op(arith_op) | cmpcc(cc) | op3(fpop2_op3) | fs1(s1, w) | opf(0x50 + w) | fs2(s2, w)); } -inline void Assembler::fcmpe( FloatRegisterImpl::Width w, CC cc, FloatRegister s1, FloatRegister s2) { emit_int32( op(arith_op) | cmpcc(cc) | op3(fpop2_op3) | fs1(s1, w) | opf(0x54 + w) | fs2(s2, w)); } - -inline void Assembler::ftox( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(fpop1_op3) | opf(0x80 + w) | fs2(s, w)); } -inline void Assembler::ftoi( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(fpop1_op3) | opf(0xd0 + w) | fs2(s, w)); } - -inline void Assembler::ftof( FloatRegisterImpl::Width sw, FloatRegisterImpl::Width dw, FloatRegister s, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, dw) | op3(fpop1_op3) | opf(0xc0 + sw + dw*4) | fs2(s, sw)); } - -inline void Assembler::fxtof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { v9_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w*4) | fs2(s, FloatRegisterImpl::D)); } -inline void Assembler::fitof( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xc0 + w*4) | fs2(s, FloatRegisterImpl::S)); } - -inline void Assembler::fmov( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x00 + w) | fs2(s, w)); } -inline void Assembler::fneg( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x04 + w) | fs2(s, w)); } -inline void Assembler::fabs( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x08 + w) | fs2(s, w)); } -inline void Assembler::fmul( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x48 + w) | fs2(s2, w)); } -inline void Assembler::fmul( FloatRegisterImpl::Width sw, FloatRegisterImpl::Width dw, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, dw) | op3(fpop1_op3) | fs1(s1, sw) | opf(0x60 + sw + dw*4) | fs2(s2, sw)); } -inline void Assembler::fdiv( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x4c + w) | fs2(s2, w)); } - -inline void Assembler::fxor( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, w) | op3(flog3_op3) | fs1(s1, w) | opf(0x6E - w) | fs2(s2, w)); } - -inline void Assembler::fsqrt( FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d ) { emit_int32( op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x28 + w) | fs2(s, w)); } - -inline void Assembler::flush( Register s1, Register s2) { emit_int32( op(arith_op) | op3(flush_op3) | rs1(s1) | rs2(s2)); } -inline void Assembler::flush( Register s1, int simm13a) { emit_data( op(arith_op) | op3(flush_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } - -inline void Assembler::flushw() { v9_only(); emit_int32( op(arith_op) | op3(flushw_op3) ); } - -inline void Assembler::illtrap( int const22a) { if (const22a != 0) v9_only(); emit_int32( op(branch_op) | u_field(const22a, 21, 0) ); } - -inline void Assembler::impdep1( int id1, int const19a ) { v9_only(); emit_int32( op(arith_op) | fcn(id1) | op3(impdep1_op3) | u_field(const19a, 18, 0)); } -inline void Assembler::impdep2( int id1, int const19a ) { v9_only(); emit_int32( op(arith_op) | fcn(id1) | op3(impdep2_op3) | u_field(const19a, 18, 0)); } - -inline void Assembler::jmpl( Register s1, Register s2, Register d ) { insert_nop_after_cbcond(); cti(); emit_int32( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); } -inline void Assembler::jmpl( Register s1, int simm13a, Register d, RelocationHolder const& rspec ) { insert_nop_after_cbcond(); cti(); emit_data( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); has_delay_slot(); } - -inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d) { emit_int32( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | rs2(s2) ); } -inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d, RelocationHolder const& rspec) { emit_data( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); } - -inline void Assembler::ldxfsr( Register s1, Register s2) { v9_only(); emit_int32( op(ldst_op) | rd(G1) | op3(ldfsr_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::ldxfsr( Register s1, int simm13a) { v9_only(); emit_data( op(ldst_op) | rd(G1) | op3(ldfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } - -inline void Assembler::ldfa( FloatRegisterImpl::Width w, Register s1, Register s2, int ia, FloatRegister d ) { v9_only(); emit_int32( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3 | alt_bit_op3, w) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::ldfa( FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d ) { v9_only(); emit_int32( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3 | alt_bit_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } - -inline void Assembler::ldsb( Register s1, Register s2, Register d) { emit_int32( op(ldst_op) | rd(d) | op3(ldsb_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::ldsb( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldsb_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } - -inline void Assembler::ldsh( Register s1, Register s2, Register d) { emit_int32( op(ldst_op) | rd(d) | op3(ldsh_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::ldsh( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldsh_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::ldsw( Register s1, Register s2, Register d) { emit_int32( op(ldst_op) | rd(d) | op3(ldsw_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::ldsw( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldsw_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::ldub( Register s1, Register s2, Register d) { emit_int32( op(ldst_op) | rd(d) | op3(ldub_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::ldub( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldub_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::lduh( Register s1, Register s2, Register d) { emit_int32( op(ldst_op) | rd(d) | op3(lduh_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::lduh( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(lduh_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::lduw( Register s1, Register s2, Register d) { emit_int32( op(ldst_op) | rd(d) | op3(lduw_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::lduw( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(lduw_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } - -inline void Assembler::ldx( Register s1, Register s2, Register d) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(ldx_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::ldx( Register s1, int simm13a, Register d) { v9_only(); emit_data( op(ldst_op) | rd(d) | op3(ldx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::ldd( Register s1, Register s2, Register d) { v9_dep(); assert(d->is_even(), "not even"); emit_int32( op(ldst_op) | rd(d) | op3(ldd_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::ldd( Register s1, int simm13a, Register d) { v9_dep(); assert(d->is_even(), "not even"); emit_data( op(ldst_op) | rd(d) | op3(ldd_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } - -inline void Assembler::ldsba( Register s1, Register s2, int ia, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::ldsba( Register s1, int simm13a, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::ldsha( Register s1, Register s2, int ia, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(ldsh_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::ldsha( Register s1, int simm13a, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(ldsh_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::ldswa( Register s1, Register s2, int ia, Register d ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(ldsw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::ldswa( Register s1, int simm13a, Register d ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(ldsw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::lduba( Register s1, Register s2, int ia, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(ldub_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::lduba( Register s1, int simm13a, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(ldub_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::lduha( Register s1, Register s2, int ia, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(lduh_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::lduha( Register s1, int simm13a, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(lduh_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::lduwa( Register s1, Register s2, int ia, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(lduw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::lduwa( Register s1, int simm13a, Register d ) { emit_int32( op(ldst_op) | rd(d) | op3(lduw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::ldxa( Register s1, Register s2, int ia, Register d ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(ldx_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::ldxa( Register s1, int simm13a, Register d ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(ldx_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } - -inline void Assembler::and3( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(and_op3 ) | rs1(s1) | rs2(s2) ); } -inline void Assembler::and3( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(and_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::andcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(and_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::andcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(and_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::andn( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(andn_op3 ) | rs1(s1) | rs2(s2) ); } -inline void Assembler::andn( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(andn_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::andncc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(andn_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::andncc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(andn_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::or3( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(or_op3 ) | rs1(s1) | rs2(s2) ); } -inline void Assembler::or3( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(or_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::orcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(or_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::orcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(or_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::orn( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(orn_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::orn( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(orn_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::orncc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(orn_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::orncc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(orn_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::xor3( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xor_op3 ) | rs1(s1) | rs2(s2) ); } -inline void Assembler::xor3( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xor_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::xorcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xor_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::xorcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xor_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::xnor( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xnor_op3 ) | rs1(s1) | rs2(s2) ); } -inline void Assembler::xnor( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xnor_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::xnorcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xnor_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::xnorcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(xnor_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } - -inline void Assembler::membar( Membar_mask_bits const7a ) { v9_only(); emit_int32( op(arith_op) | op3(membar_op3) | rs1(O7) | immed(true) | u_field( int(const7a), 6, 0)); } - -inline void Assembler::fmov( FloatRegisterImpl::Width w, Condition c, bool floatCC, CC cca, FloatRegister s2, FloatRegister d ) { v9_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fpop2_op3) | cond_mov(c) | opf_cc(cca, floatCC) | opf_low6(w) | fs2(s2, w)); } - -inline void Assembler::fmov( FloatRegisterImpl::Width w, RCondition c, Register s1, FloatRegister s2, FloatRegister d ) { v9_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fpop2_op3) | rs1(s1) | rcond(c) | opf_low5(4 + w) | fs2(s2, w)); } - -inline void Assembler::movcc( Condition c, bool floatCC, CC cca, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(movcc_op3) | mov_cc(cca, floatCC) | cond_mov(c) | rs2(s2) ); } -inline void Assembler::movcc( Condition c, bool floatCC, CC cca, int simm11a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(movcc_op3) | mov_cc(cca, floatCC) | cond_mov(c) | immed(true) | simm(simm11a, 11) ); } - -inline void Assembler::movr( RCondition c, Register s1, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(movr_op3) | rs1(s1) | rcond(c) | rs2(s2) ); } -inline void Assembler::movr( RCondition c, Register s1, int simm10a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(movr_op3) | rs1(s1) | rcond(c) | immed(true) | simm(simm10a, 10) ); } - -inline void Assembler::mulx( Register s1, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(mulx_op3 ) | rs1(s1) | rs2(s2) ); } -inline void Assembler::mulx( Register s1, int simm13a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(mulx_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::sdivx( Register s1, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(sdivx_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::sdivx( Register s1, int simm13a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(sdivx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::udivx( Register s1, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(udivx_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::udivx( Register s1, int simm13a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(udivx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } - -inline void Assembler::umul( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(umul_op3 ) | rs1(s1) | rs2(s2) ); } -inline void Assembler::umul( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(umul_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::smul( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(smul_op3 ) | rs1(s1) | rs2(s2) ); } -inline void Assembler::smul( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(smul_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::umulcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(umul_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::umulcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(umul_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::smulcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(smul_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::smulcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(smul_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } - -inline void Assembler::nop() { emit_int32( op(branch_op) | op2(sethi_op2) ); } - -inline void Assembler::sw_count() { emit_int32( op(branch_op) | op2(sethi_op2) | 0x3f0 ); } - -inline void Assembler::popc( Register s, Register d) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(popc_op3) | rs2(s)); } -inline void Assembler::popc( int simm13a, Register d) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(popc_op3) | immed(true) | simm(simm13a, 13)); } - -inline void Assembler::prefetch( Register s1, Register s2, PrefetchFcn f) { v9_only(); emit_int32( op(ldst_op) | fcn(f) | op3(prefetch_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::prefetch( Register s1, int simm13a, PrefetchFcn f) { v9_only(); emit_data( op(ldst_op) | fcn(f) | op3(prefetch_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } - -inline void Assembler::prefetcha( Register s1, Register s2, int ia, PrefetchFcn f ) { v9_only(); emit_int32( op(ldst_op) | fcn(f) | op3(prefetch_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::prefetcha( Register s1, int simm13a, PrefetchFcn f ) { v9_only(); emit_int32( op(ldst_op) | fcn(f) | op3(prefetch_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } - -inline void Assembler::rdy( Register d) { v9_dep(); emit_int32( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(0, 18, 14)); } -inline void Assembler::rdccr( Register d) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(2, 18, 14)); } -inline void Assembler::rdasi( Register d) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(3, 18, 14)); } -inline void Assembler::rdtick( Register d) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(4, 18, 14)); } // Spoon! -inline void Assembler::rdpc( Register d) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(5, 18, 14)); } -inline void Assembler::rdfprs( Register d) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(6, 18, 14)); } - -inline void Assembler::rett( Register s1, Register s2 ) { cti(); emit_int32( op(arith_op) | op3(rett_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); } -inline void Assembler::rett( Register s1, int simm13a, relocInfo::relocType rt) { cti(); emit_data( op(arith_op) | op3(rett_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rt); has_delay_slot(); } - -inline void Assembler::save( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(save_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::save( Register s1, int simm13a, Register d ) { - // make sure frame is at least large enough for the register save area - assert(-simm13a >= 16 * wordSize, "frame too small"); - emit_int32( op(arith_op) | rd(d) | op3(save_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); +inline void Assembler::aes_kexpand0(FloatRegister s1, FloatRegister s2, FloatRegister d) { + aes_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes3_op3) | fs1(s1, FloatRegisterImpl::D) | opf(aes_kexpand0_opf) | fs2(s2, FloatRegisterImpl::D)); +} +inline void Assembler::aes_kexpand2(FloatRegister s1, FloatRegister s2, FloatRegister d) { + aes_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(aes3_op3) | fs1(s1, FloatRegisterImpl::D) | opf(aes_kexpand2_opf) | fs2(s2, FloatRegisterImpl::D)); } -inline void Assembler::restore( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(restore_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::restore( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(restore_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } +inline void Assembler::bpr(RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt) { + avoid_pipeline_stall(); + cti(); + emit_data(op(branch_op) | annul(a) | cond(c) | op2(bpr_op2) | wdisp16(intptr_t(d), intptr_t(pc())) | predict(p) | rs1(s1), rt); + induce_delay_slot(); +} +inline void Assembler::bpr(RCondition c, bool a, Predict p, Register s1, Label &L) { + // Note[+]: All assembly emit routines using the 'target()' branch back-patch + // resolver must call 'avoid_pipeline_stall()' prior to calling 'target()' + // (we must do so even though the call will be made, as here, in the above + // implementation of 'bpr()', invoked below). The reason is the assumption + // made in 'target()', where using the current PC as the address for back- + // patching prevents any additional code to be emitted _after_ the address + // has been set (implicitly) in order to refer to the correct instruction. + avoid_pipeline_stall(); + bpr(c, a, p, s1, target(L)); +} + +inline void Assembler::fb(Condition c, bool a, address d, relocInfo::relocType rt) { + v9_dep(); + avoid_pipeline_stall(); + cti(); + emit_data(op(branch_op) | annul(a) | cond(c) | op2(fb_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); + induce_delay_slot(); +} +inline void Assembler::fb(Condition c, bool a, Label &L) { + avoid_pipeline_stall(); + fb(c, a, target(L)); +} + +inline void Assembler::fbp(Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt) { + avoid_pipeline_stall(); + cti(); + emit_data(op(branch_op) | annul(a) | cond(c) | op2(fbp_op2) | branchcc(cc) | predict(p) | wdisp(intptr_t(d), intptr_t(pc()), 19), rt); + induce_delay_slot(); +} +inline void Assembler::fbp(Condition c, bool a, CC cc, Predict p, Label &L) { + avoid_pipeline_stall(); + fbp(c, a, cc, p, target(L)); +} + +inline void Assembler::br(Condition c, bool a, address d, relocInfo::relocType rt) { + v9_dep(); + avoid_pipeline_stall(); + cti(); + emit_data(op(branch_op) | annul(a) | cond(c) | op2(br_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); + induce_delay_slot(); +} +inline void Assembler::br(Condition c, bool a, Label &L) { + avoid_pipeline_stall(); + br(c, a, target(L)); +} + +inline void Assembler::bp(Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt) { + avoid_pipeline_stall(); + cti(); + emit_data(op(branch_op) | annul(a) | cond(c) | op2(bp_op2) | branchcc(cc) | predict(p) | wdisp(intptr_t(d), intptr_t(pc()), 19), rt); + induce_delay_slot(); +} +inline void Assembler::bp(Condition c, bool a, CC cc, Predict p, Label &L) { + avoid_pipeline_stall(); + bp(c, a, cc, p, target(L)); +} + +// compare and branch +inline void Assembler::cbcond(Condition c, CC cc, Register s1, Register s2, Label &L) { + avoid_pipeline_stall(); + cti(); + emit_data(op(branch_op) | cond_cbcond(c) | op2(bpr_op2) | branchcc(cc) | wdisp10(intptr_t(target(L)), intptr_t(pc())) | rs1(s1) | rs2(s2)); + induce_pc_hazard(); +} +inline void Assembler::cbcond(Condition c, CC cc, Register s1, int simm5, Label &L) { + avoid_pipeline_stall(); + cti(); + emit_data(op(branch_op) | cond_cbcond(c) | op2(bpr_op2) | branchcc(cc) | wdisp10(intptr_t(target(L)), intptr_t(pc())) | rs1(s1) | immed(true) | simm(simm5, 5)); + induce_pc_hazard(); +} + +inline void Assembler::call(address d, relocInfo::relocType rt) { + avoid_pipeline_stall(); + cti(); + emit_data(op(call_op) | wdisp(intptr_t(d), intptr_t(pc()), 30), rt); + induce_delay_slot(); + assert(rt != relocInfo::virtual_call_type, "must use virtual_call_Relocation::spec"); +} +inline void Assembler::call(Label &L, relocInfo::relocType rt) { + avoid_pipeline_stall(); + call(target(L), rt); +} + +inline void Assembler::call(address d, RelocationHolder const &rspec) { + avoid_pipeline_stall(); + cti(); + emit_data(op(call_op) | wdisp(intptr_t(d), intptr_t(pc()), 30), rspec); + induce_delay_slot(); + assert(rspec.type() != relocInfo::virtual_call_type, "must use virtual_call_Relocation::spec"); +} + +inline void Assembler::casa(Register s1, Register s2, Register d, int ia) { + emit_int32(op(ldst_op) | rd(d) | op3(casa_op3) | rs1(s1) | (ia == -1 ? immed(true) : imm_asi(ia)) | rs2(s2)); +} +inline void Assembler::casxa(Register s1, Register s2, Register d, int ia) { + emit_int32(op(ldst_op) | rd(d) | op3(casxa_op3) | rs1(s1) | (ia == -1 ? immed(true) : imm_asi(ia)) | rs2(s2)); +} + +inline void Assembler::udiv(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(udiv_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::udiv(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(udiv_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::sdiv(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sdiv_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::sdiv(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sdiv_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::udivcc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(udiv_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::udivcc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(udiv_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::sdivcc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sdiv_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::sdivcc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sdiv_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::done() { + cti(); + emit_int32(op(arith_op) | fcn(0) | op3(done_op3)); +} +inline void Assembler::retry() { + cti(); + emit_int32(op(arith_op) | fcn(1) | op3(retry_op3)); +} + +inline void Assembler::fadd(FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x40 + w) | fs2(s2, w)); +} +inline void Assembler::fsub(FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x44 + w) | fs2(s2, w)); +} + +inline void Assembler::fcmp(FloatRegisterImpl::Width w, CC cc, FloatRegister s1, FloatRegister s2) { + emit_int32(op(arith_op) | cmpcc(cc) | op3(fpop2_op3) | fs1(s1, w) | opf(0x50 + w) | fs2(s2, w)); +} +inline void Assembler::fcmpe(FloatRegisterImpl::Width w, CC cc, FloatRegister s1, FloatRegister s2) { + emit_int32(op(arith_op) | cmpcc(cc) | op3(fpop2_op3) | fs1(s1, w) | opf(0x54 + w) | fs2(s2, w)); +} + +inline void Assembler::ftox(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(fpop1_op3) | opf(0x80 + w) | fs2(s, w)); +} +inline void Assembler::ftoi(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(fpop1_op3) | opf(0xd0 + w) | fs2(s, w)); +} + +inline void Assembler::ftof(FloatRegisterImpl::Width sw, FloatRegisterImpl::Width dw, FloatRegister s, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, dw) | op3(fpop1_op3) | opf(0xc0 + sw + dw*4) | fs2(s, sw)); +} + +inline void Assembler::fxtof(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x80 + w*4) | fs2(s, FloatRegisterImpl::D)); +} +inline void Assembler::fitof(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0xc0 + w*4) | fs2(s, FloatRegisterImpl::S)); +} + +inline void Assembler::fmov(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x00 + w) | fs2(s, w)); +} +inline void Assembler::fneg(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x04 + w) | fs2(s, w)); +} +inline void Assembler::fabs(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x08 + w) | fs2(s, w)); +} +inline void Assembler::fmul(FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x48 + w) | fs2(s2, w)); +} +inline void Assembler::fmul(FloatRegisterImpl::Width sw, FloatRegisterImpl::Width dw, FloatRegister s1, FloatRegister s2, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, dw) | op3(fpop1_op3) | fs1(s1, sw) | opf(0x60 + sw + dw*4) | fs2(s2, sw)); +} +inline void Assembler::fdiv(FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, w) | op3(fpop1_op3) | fs1(s1, w) | opf(0x4c + w) | fs2(s2, w)); +} + +inline void Assembler::fxor(FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister d) { + vis1_only(); + emit_int32(op(arith_op) | fd(d, w) | op3(flog3_op3) | fs1(s1, w) | opf(0x6E - w) | fs2(s2, w)); +} + +inline void Assembler::fsqrt(FloatRegisterImpl::Width w, FloatRegister s, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, w) | op3(fpop1_op3) | opf(0x28 + w) | fs2(s, w)); +} + +inline void Assembler::fmadd(FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister s2, FloatRegister s3, FloatRegister d) { + fmaf_only(); + emit_int32(op(arith_op) | fd(d, w) | op3(stpartialf_op3) | fs1(s1, w) | fs3(s3, w) | op5(w) | fs2(s2, w)); +} + +inline void Assembler::flush(Register s1, Register s2) { + emit_int32(op(arith_op) | op3(flush_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::flush(Register s1, int simm13a) { + emit_data(op(arith_op) | op3(flush_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::flushw() { + emit_int32(op(arith_op) | op3(flushw_op3)); +} + +inline void Assembler::illtrap(int const22a) { + emit_int32(op(branch_op) | u_field(const22a, 21, 0)); +} + +inline void Assembler::impdep1(int id1, int const19a) { + emit_int32(op(arith_op) | fcn(id1) | op3(impdep1_op3) | u_field(const19a, 18, 0)); +} +inline void Assembler::impdep2(int id1, int const19a) { + emit_int32(op(arith_op) | fcn(id1) | op3(impdep2_op3) | u_field(const19a, 18, 0)); +} + +inline void Assembler::jmpl(Register s1, Register s2, Register d) { + avoid_pipeline_stall(); + cti(); + emit_int32(op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | rs2(s2)); + induce_delay_slot(); +} +inline void Assembler::jmpl(Register s1, int simm13a, Register d, RelocationHolder const &rspec) { + avoid_pipeline_stall(); + cti(); + emit_data(op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); + induce_delay_slot(); +} + +inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d) { + emit_int32(op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | rs2(s2)); +} +inline void Assembler::ldf(FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d, RelocationHolder const &rspec) { + emit_data(op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); +} + +inline void Assembler::ldxfsr(Register s1, Register s2) { + emit_int32(op(ldst_op) | rd(G1) | op3(ldfsr_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::ldxfsr(Register s1, int simm13a) { + emit_data(op(ldst_op) | rd(G1) | op3(ldfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::ldfa(FloatRegisterImpl::Width w, Register s1, Register s2, int ia, FloatRegister d) { + emit_int32(op(ldst_op) | fd(d, w) | alt_op3(ldf_op3 | alt_bit_op3, w) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::ldfa(FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d) { + emit_int32(op(ldst_op) | fd(d, w) | alt_op3(ldf_op3 | alt_bit_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::ldsb(Register s1, Register s2, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldsb_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::ldsb(Register s1, int simm13a, Register d) { + emit_data(op(ldst_op) | rd(d) | op3(ldsb_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::ldsh(Register s1, Register s2, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldsh_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::ldsh(Register s1, int simm13a, Register d) { + emit_data(op(ldst_op) | rd(d) | op3(ldsh_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::ldsw(Register s1, Register s2, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldsw_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::ldsw(Register s1, int simm13a, Register d) { + emit_data(op(ldst_op) | rd(d) | op3(ldsw_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::ldub(Register s1, Register s2, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldub_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::ldub(Register s1, int simm13a, Register d) { + emit_data(op(ldst_op) | rd(d) | op3(ldub_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::lduh(Register s1, Register s2, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(lduh_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::lduh(Register s1, int simm13a, Register d) { + emit_data(op(ldst_op) | rd(d) | op3(lduh_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::lduw(Register s1, Register s2, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(lduw_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::lduw(Register s1, int simm13a, Register d) { + emit_data(op(ldst_op) | rd(d) | op3(lduw_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::ldx(Register s1, Register s2, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldx_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::ldx(Register s1, int simm13a, Register d) { + emit_data(op(ldst_op) | rd(d) | op3(ldx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::ldd(Register s1, Register s2, Register d) { + v9_dep(); + assert(d->is_even(), "not even"); + emit_int32(op(ldst_op) | rd(d) | op3(ldd_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::ldd(Register s1, int simm13a, Register d) { + v9_dep(); + assert(d->is_even(), "not even"); + emit_data(op(ldst_op) | rd(d) | op3(ldd_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::ldsba(Register s1, Register s2, int ia, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::ldsba(Register s1, int simm13a, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldsb_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::ldsha(Register s1, Register s2, int ia, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldsh_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::ldsha(Register s1, int simm13a, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldsh_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::ldswa(Register s1, Register s2, int ia, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldsw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::ldswa(Register s1, int simm13a, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldsw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::lduba(Register s1, Register s2, int ia, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldub_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::lduba(Register s1, int simm13a, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldub_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::lduha(Register s1, Register s2, int ia, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(lduh_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::lduha(Register s1, int simm13a, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(lduh_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::lduwa(Register s1, Register s2, int ia, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(lduw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::lduwa(Register s1, int simm13a, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(lduw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::ldxa(Register s1, Register s2, int ia, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldx_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::ldxa(Register s1, int simm13a, Register d) { + emit_int32(op(ldst_op) | rd(d) | op3(ldx_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::and3(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(and_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::and3(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(and_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::andcc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(and_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::andcc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(and_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::andn(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(andn_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::andn(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(andn_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::andncc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(andn_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::andncc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(andn_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::or3(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(or_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::or3(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(or_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::orcc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(or_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::orcc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(or_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::orn(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(orn_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::orn(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(orn_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::orncc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(orn_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::orncc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(orn_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::xor3(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(xor_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::xor3(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(xor_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::xorcc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(xor_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::xorcc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(xor_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::xnor(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(xnor_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::xnor(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(xnor_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::xnorcc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(xnor_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::xnorcc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(xnor_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::membar(Membar_mask_bits const7a) { + emit_int32(op(arith_op) | op3(membar_op3) | rs1(O7) | immed(true) | u_field(int(const7a), 6, 0)); +} + +inline void Assembler::fmov(FloatRegisterImpl::Width w, Condition c, bool floatCC, CC cca, FloatRegister s2, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, w) | op3(fpop2_op3) | cond_mov(c) | opf_cc(cca, floatCC) | opf_low6(w) | fs2(s2, w)); +} + +inline void Assembler::fmov(FloatRegisterImpl::Width w, RCondition c, Register s1, FloatRegister s2, FloatRegister d) { + emit_int32(op(arith_op) | fd(d, w) | op3(fpop2_op3) | rs1(s1) | rcond(c) | opf_low5(4 + w) | fs2(s2, w)); +} + +inline void Assembler::movcc(Condition c, bool floatCC, CC cca, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(movcc_op3) | mov_cc(cca, floatCC) | cond_mov(c) | rs2(s2)); +} +inline void Assembler::movcc(Condition c, bool floatCC, CC cca, int simm11a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(movcc_op3) | mov_cc(cca, floatCC) | cond_mov(c) | immed(true) | simm(simm11a, 11)); +} + +inline void Assembler::movr(RCondition c, Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(movr_op3) | rs1(s1) | rcond(c) | rs2(s2)); +} +inline void Assembler::movr(RCondition c, Register s1, int simm10a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(movr_op3) | rs1(s1) | rcond(c) | immed(true) | simm(simm10a, 10)); +} + +inline void Assembler::mulx(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(mulx_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::mulx(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(mulx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::sdivx(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sdivx_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::sdivx(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sdivx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::udivx(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(udivx_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::udivx(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(udivx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::umul(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(umul_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::umul(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(umul_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::smul(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(smul_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::smul(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(smul_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::umulcc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(umul_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::umulcc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(umul_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::smulcc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(smul_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::smulcc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(smul_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::nop() { + emit_int32(op(branch_op) | op2(sethi_op2)); +} + +inline void Assembler::sw_count() { + emit_int32(op(branch_op) | op2(sethi_op2) | 0x3f0); +} + +inline void Assembler::popc(Register s, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(popc_op3) | rs2(s)); +} +inline void Assembler::popc(int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(popc_op3) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::prefetch(Register s1, Register s2, PrefetchFcn f) { + emit_int32(op(ldst_op) | fcn(f) | op3(prefetch_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::prefetch(Register s1, int simm13a, PrefetchFcn f) { + emit_data(op(ldst_op) | fcn(f) | op3(prefetch_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::prefetcha(Register s1, Register s2, int ia, PrefetchFcn f) { + emit_int32(op(ldst_op) | fcn(f) | op3(prefetch_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::prefetcha(Register s1, int simm13a, PrefetchFcn f) { + emit_int32(op(ldst_op) | fcn(f) | op3(prefetch_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::rdy(Register d) { + v9_dep(); + emit_int32(op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(0, 18, 14)); +} +inline void Assembler::rdccr(Register d) { + emit_int32(op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(2, 18, 14)); +} +inline void Assembler::rdasi(Register d) { + emit_int32(op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(3, 18, 14)); +} +inline void Assembler::rdtick(Register d) { + emit_int32(op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(4, 18, 14)); +} +inline void Assembler::rdpc(Register d) { + avoid_pipeline_stall(); + cti(); + emit_int32(op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(5, 18, 14)); + induce_pc_hazard(); +} +inline void Assembler::rdfprs(Register d) { + emit_int32(op(arith_op) | rd(d) | op3(rdreg_op3) | u_field(6, 18, 14)); +} + +inline void Assembler::rett(Register s1, Register s2) { + cti(); + emit_int32(op(arith_op) | op3(rett_op3) | rs1(s1) | rs2(s2)); + induce_delay_slot(); +} +inline void Assembler::rett(Register s1, int simm13a, relocInfo::relocType rt) { + cti(); + emit_data(op(arith_op) | op3(rett_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rt); + induce_delay_slot(); +} + +inline void Assembler::save(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(save_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::save(Register s1, int simm13a, Register d) { + // make sure frame is at least large enough for the register save area + assert(-simm13a >= 16 * wordSize, "frame too small"); + emit_int32(op(arith_op) | rd(d) | op3(save_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} + +inline void Assembler::restore(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(restore_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::restore(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(restore_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} // pp 216 -inline void Assembler::saved() { v9_only(); emit_int32( op(arith_op) | fcn(0) | op3(saved_op3)); } -inline void Assembler::restored() { v9_only(); emit_int32( op(arith_op) | fcn(1) | op3(saved_op3)); } +inline void Assembler::saved() { + emit_int32(op(arith_op) | fcn(0) | op3(saved_op3)); +} +inline void Assembler::restored() { + emit_int32(op(arith_op) | fcn(1) | op3(saved_op3)); +} -inline void Assembler::sethi( int imm22a, Register d, RelocationHolder const& rspec ) { emit_data( op(branch_op) | rd(d) | op2(sethi_op2) | hi22(imm22a), rspec); } +inline void Assembler::sethi(int imm22a, Register d, RelocationHolder const &rspec) { + emit_data(op(branch_op) | rd(d) | op2(sethi_op2) | hi22(imm22a), rspec); +} -inline void Assembler::sll( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(0) | rs2(s2) ); } -inline void Assembler::sll( Register s1, int imm5a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0) ); } -inline void Assembler::srl( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(0) | rs2(s2) ); } -inline void Assembler::srl( Register s1, int imm5a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0) ); } -inline void Assembler::sra( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(0) | rs2(s2) ); } -inline void Assembler::sra( Register s1, int imm5a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0) ); } +inline void Assembler::sll(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(0) | rs2(s2)); +} +inline void Assembler::sll(Register s1, int imm5a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0)); +} +inline void Assembler::srl(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(0) | rs2(s2)); +} +inline void Assembler::srl(Register s1, int imm5a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0)); +} +inline void Assembler::sra(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(0) | rs2(s2)); +} +inline void Assembler::sra(Register s1, int imm5a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(0) | immed(true) | u_field(imm5a, 4, 0)); +} -inline void Assembler::sllx( Register s1, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(1) | rs2(s2) ); } -inline void Assembler::sllx( Register s1, int imm6a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0) ); } -inline void Assembler::srlx( Register s1, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(1) | rs2(s2) ); } -inline void Assembler::srlx( Register s1, int imm6a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0) ); } -inline void Assembler::srax( Register s1, Register s2, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(1) | rs2(s2) ); } -inline void Assembler::srax( Register s1, int imm6a, Register d ) { v9_only(); emit_int32( op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0) ); } +inline void Assembler::sllx(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(1) | rs2(s2)); +} +inline void Assembler::sllx(Register s1, int imm6a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sll_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0)); +} +inline void Assembler::srlx(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(1) | rs2(s2)); +} +inline void Assembler::srlx(Register s1, int imm6a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(srl_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0)); +} +inline void Assembler::srax(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(1) | rs2(s2)); +} +inline void Assembler::srax(Register s1, int imm6a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sra_op3) | rs1(s1) | sx(1) | immed(true) | u_field(imm6a, 5, 0)); +} -inline void Assembler::sir( int simm13a ) { emit_int32( op(arith_op) | fcn(15) | op3(sir_op3) | immed(true) | simm(simm13a, 13)); } +inline void Assembler::sir(int simm13a) { + emit_int32(op(arith_op) | fcn(15) | op3(sir_op3) | immed(true) | simm(simm13a, 13)); +} - // pp 221 +// pp 221 -inline void Assembler::stbar() { emit_int32( op(arith_op) | op3(membar_op3) | u_field(15, 18, 14)); } +inline void Assembler::stbar() { + emit_int32(op(arith_op) | op3(membar_op3) | u_field(15, 18, 14)); +} - // pp 222 +// pp 222 -inline void Assembler::stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2) { emit_int32( op(ldst_op) | fd(d, w) | alt_op3(stf_op3, w) | rs1(s1) | rs2(s2) ); } -inline void Assembler::stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a) { emit_data( op(ldst_op) | fd(d, w) | alt_op3(stf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13)); } +inline void Assembler::stf(FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2) { + emit_int32(op(ldst_op) | fd(d, w) | alt_op3(stf_op3, w) | rs1(s1) | rs2(s2)); +} +inline void Assembler::stf(FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a) { + emit_data(op(ldst_op) | fd(d, w) | alt_op3(stf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} -inline void Assembler::stxfsr( Register s1, Register s2) { v9_only(); emit_int32( op(ldst_op) | rd(G1) | op3(stfsr_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::stxfsr( Register s1, int simm13a) { v9_only(); emit_data( op(ldst_op) | rd(G1) | op3(stfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } +inline void Assembler::stxfsr(Register s1, Register s2) { + emit_int32(op(ldst_op) | rd(G1) | op3(stfsr_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::stxfsr(Register s1, int simm13a) { + emit_data(op(ldst_op) | rd(G1) | op3(stfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} -inline void Assembler::stfa( FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2, int ia ) { v9_only(); emit_int32( op(ldst_op) | fd(d, w) | alt_op3(stf_op3 | alt_bit_op3, w) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::stfa( FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a ) { v9_only(); emit_int32( op(ldst_op) | fd(d, w) | alt_op3(stf_op3 | alt_bit_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } +inline void Assembler::stfa(FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2, int ia) { + emit_int32(op(ldst_op) | fd(d, w) | alt_op3(stf_op3 | alt_bit_op3, w) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::stfa(FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a) { + emit_int32(op(ldst_op) | fd(d, w) | alt_op3(stf_op3 | alt_bit_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} - // p 226 +// p 226 -inline void Assembler::stb( Register d, Register s1, Register s2) { emit_int32( op(ldst_op) | rd(d) | op3(stb_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::stb( Register d, Register s1, int simm13a) { emit_data( op(ldst_op) | rd(d) | op3(stb_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::sth( Register d, Register s1, Register s2) { emit_int32( op(ldst_op) | rd(d) | op3(sth_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::sth( Register d, Register s1, int simm13a) { emit_data( op(ldst_op) | rd(d) | op3(sth_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::stw( Register d, Register s1, Register s2) { emit_int32( op(ldst_op) | rd(d) | op3(stw_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::stw( Register d, Register s1, int simm13a) { emit_data( op(ldst_op) | rd(d) | op3(stw_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } +inline void Assembler::stb(Register d, Register s1, Register s2) { + emit_int32(op(ldst_op) | rd(d) | op3(stb_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::stb(Register d, Register s1, int simm13a) { + emit_data(op(ldst_op) | rd(d) | op3(stb_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::sth(Register d, Register s1, Register s2) { + emit_int32(op(ldst_op) | rd(d) | op3(sth_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::sth(Register d, Register s1, int simm13a) { + emit_data(op(ldst_op) | rd(d) | op3(sth_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::stw(Register d, Register s1, Register s2) { + emit_int32(op(ldst_op) | rd(d) | op3(stw_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::stw(Register d, Register s1, int simm13a) { + emit_data(op(ldst_op) | rd(d) | op3(stw_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} -inline void Assembler::stx( Register d, Register s1, Register s2) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(stx_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::stx( Register d, Register s1, int simm13a) { v9_only(); emit_data( op(ldst_op) | rd(d) | op3(stx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::std( Register d, Register s1, Register s2) { v9_dep(); assert(d->is_even(), "not even"); emit_int32( op(ldst_op) | rd(d) | op3(std_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::std( Register d, Register s1, int simm13a) { v9_dep(); assert(d->is_even(), "not even"); emit_data( op(ldst_op) | rd(d) | op3(std_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } +inline void Assembler::stx(Register d, Register s1, Register s2) { + emit_int32(op(ldst_op) | rd(d) | op3(stx_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::stx(Register d, Register s1, int simm13a) { + emit_data(op(ldst_op) | rd(d) | op3(stx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::std(Register d, Register s1, Register s2) { + v9_dep(); + assert(d->is_even(), "not even"); + emit_int32(op(ldst_op) | rd(d) | op3(std_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::std(Register d, Register s1, int simm13a) { + v9_dep(); + assert(d->is_even(), "not even"); + emit_data(op(ldst_op) | rd(d) | op3(std_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} -inline void Assembler::stba( Register d, Register s1, Register s2, int ia ) { emit_int32( op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::stba( Register d, Register s1, int simm13a ) { emit_int32( op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::stha( Register d, Register s1, Register s2, int ia ) { emit_int32( op(ldst_op) | rd(d) | op3(sth_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::stha( Register d, Register s1, int simm13a ) { emit_int32( op(ldst_op) | rd(d) | op3(sth_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::stwa( Register d, Register s1, Register s2, int ia ) { emit_int32( op(ldst_op) | rd(d) | op3(stw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::stwa( Register d, Register s1, int simm13a ) { emit_int32( op(ldst_op) | rd(d) | op3(stw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::stxa( Register d, Register s1, Register s2, int ia ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(stx_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::stxa( Register d, Register s1, int simm13a ) { v9_only(); emit_int32( op(ldst_op) | rd(d) | op3(stx_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::stda( Register d, Register s1, Register s2, int ia ) { emit_int32( op(ldst_op) | rd(d) | op3(std_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::stda( Register d, Register s1, int simm13a ) { emit_int32( op(ldst_op) | rd(d) | op3(std_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } +inline void Assembler::stba(Register d, Register s1, Register s2, int ia) { + emit_int32(op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::stba(Register d, Register s1, int simm13a) { + emit_int32(op(ldst_op) | rd(d) | op3(stb_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::stha(Register d, Register s1, Register s2, int ia) { + emit_int32(op(ldst_op) | rd(d) | op3(sth_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::stha(Register d, Register s1, int simm13a) { + emit_int32(op(ldst_op) | rd(d) | op3(sth_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::stwa(Register d, Register s1, Register s2, int ia) { + emit_int32(op(ldst_op) | rd(d) | op3(stw_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::stwa(Register d, Register s1, int simm13a) { + emit_int32(op(ldst_op) | rd(d) | op3(stw_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::stxa(Register d, Register s1, Register s2, int ia) { + emit_int32(op(ldst_op) | rd(d) | op3(stx_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::stxa(Register d, Register s1, int simm13a) { + emit_int32(op(ldst_op) | rd(d) | op3(stx_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::stda(Register d, Register s1, Register s2, int ia) { + emit_int32(op(ldst_op) | rd(d) | op3(std_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::stda(Register d, Register s1, int simm13a) { + emit_int32(op(ldst_op) | rd(d) | op3(std_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} // pp 230 -inline void Assembler::sub( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | rs2(s2) ); } -inline void Assembler::sub( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sub_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } +inline void Assembler::sub(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sub_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::sub(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sub_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} -inline void Assembler::subcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | rs2(s2) ); } -inline void Assembler::subcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::subc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(subc_op3 ) | rs1(s1) | rs2(s2) ); } -inline void Assembler::subc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(subc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } -inline void Assembler::subccc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(subc_op3 | cc_bit_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::subccc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(subc_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } +inline void Assembler::subcc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::subcc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(sub_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::subc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(subc_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::subc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(subc_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::subccc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(subc_op3 | cc_bit_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::subccc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(subc_op3 | cc_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} // pp 231 -inline void Assembler::swap( Register s1, Register s2, Register d) { v9_dep(); emit_int32( op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | rs2(s2) ); } -inline void Assembler::swap( Register s1, int simm13a, Register d) { v9_dep(); emit_data( op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } +inline void Assembler::swap(Register s1, Register s2, Register d) { + v9_dep(); + emit_int32(op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::swap(Register s1, int simm13a, Register d) { + v9_dep(); + emit_data(op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} -inline void Assembler::swapa( Register s1, Register s2, int ia, Register d ) { v9_dep(); emit_int32( op(ldst_op) | rd(d) | op3(swap_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2) ); } -inline void Assembler::swapa( Register s1, int simm13a, Register d ) { v9_dep(); emit_int32( op(ldst_op) | rd(d) | op3(swap_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } +inline void Assembler::swapa(Register s1, Register s2, int ia, Register d) { + v9_dep(); + emit_int32(op(ldst_op) | rd(d) | op3(swap_op3 | alt_bit_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} +inline void Assembler::swapa(Register s1, int simm13a, Register d) { + v9_dep(); + emit_int32(op(ldst_op) | rd(d) | op3(swap_op3 | alt_bit_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} // pp 234, note op in book is wrong, see pp 268 -inline void Assembler::taddcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(taddcc_op3 ) | rs1(s1) | rs2(s2) ); } -inline void Assembler::taddcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(taddcc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } +inline void Assembler::taddcc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(taddcc_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::taddcc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(taddcc_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} // pp 235 -inline void Assembler::tsubcc( Register s1, Register s2, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(tsubcc_op3 ) | rs1(s1) | rs2(s2) ); } -inline void Assembler::tsubcc( Register s1, int simm13a, Register d ) { emit_int32( op(arith_op) | rd(d) | op3(tsubcc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13) ); } +inline void Assembler::tsubcc(Register s1, Register s2, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(tsubcc_op3) | rs1(s1) | rs2(s2)); +} +inline void Assembler::tsubcc(Register s1, int simm13a, Register d) { + emit_int32(op(arith_op) | rd(d) | op3(tsubcc_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); +} // pp 237 -inline void Assembler::trap( Condition c, CC cc, Register s1, Register s2 ) { emit_int32( op(arith_op) | cond(c) | op3(trap_op3) | rs1(s1) | trapcc(cc) | rs2(s2)); } -inline void Assembler::trap( Condition c, CC cc, Register s1, int trapa ) { emit_int32( op(arith_op) | cond(c) | op3(trap_op3) | rs1(s1) | trapcc(cc) | immed(true) | u_field(trapa, 6, 0)); } +inline void Assembler::trap(Condition c, CC cc, Register s1, Register s2) { + emit_int32(op(arith_op) | cond(c) | op3(trap_op3) | rs1(s1) | trapcc(cc) | rs2(s2)); +} +inline void Assembler::trap(Condition c, CC cc, Register s1, int trapa) { + emit_int32(op(arith_op) | cond(c) | op3(trap_op3) | rs1(s1) | trapcc(cc) | immed(true) | u_field(trapa, 6, 0)); +} // simple uncond. trap -inline void Assembler::trap( int trapa ) { trap( always, icc, G0, trapa ); } +inline void Assembler::trap(int trapa) { + trap(always, icc, G0, trapa); +} -inline void Assembler::wry(Register d) { v9_dep(); emit_int32(op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(0, 29, 25)); } -inline void Assembler::wrccr(Register s) { v9_only(); emit_int32(op(arith_op) | rs1(s) | op3(wrreg_op3) | u_field(2, 29, 25)); } -inline void Assembler::wrccr(Register s, int simm13a) { v9_only(); emit_int32(op(arith_op) | rs1(s) | op3(wrreg_op3) | u_field(2, 29, 25) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::wrasi(Register d) { v9_only(); emit_int32(op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(3, 29, 25)); } +inline void Assembler::wry(Register d) { + v9_dep(); + emit_int32(op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(0, 29, 25)); +} +inline void Assembler::wrccr(Register s) { + emit_int32(op(arith_op) | rs1(s) | op3(wrreg_op3) | u_field(2, 29, 25)); +} +inline void Assembler::wrccr(Register s, int simm13a) { + emit_int32(op(arith_op) | rs1(s) | op3(wrreg_op3) | u_field(2, 29, 25) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::wrasi(Register d) { + emit_int32(op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(3, 29, 25)); +} // wrasi(d, imm) stores (d xor imm) to asi -inline void Assembler::wrasi(Register d, int simm13a) { v9_only(); emit_int32(op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(3, 29, 25) | immed(true) | simm(simm13a, 13)); } -inline void Assembler::wrfprs(Register d) { v9_only(); emit_int32(op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(6, 29, 25)); } +inline void Assembler::wrasi(Register d, int simm13a) { + emit_int32(op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(3, 29, 25) | immed(true) | simm(simm13a, 13)); +} +inline void Assembler::wrfprs(Register d) { + emit_int32(op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(6, 29, 25)); +} -inline void Assembler::alignaddr( Register s1, Register s2, Register d ) { vis1_only(); emit_int32( op(arith_op) | rd(d) | op3(alignaddr_op3) | rs1(s1) | opf(alignaddr_opf) | rs2(s2)); } +inline void Assembler::alignaddr(Register s1, Register s2, Register d) { + vis1_only(); + emit_int32(op(arith_op) | rd(d) | op3(alignaddr_op3) | rs1(s1) | opf(alignaddr_opf) | rs2(s2)); +} -inline void Assembler::faligndata( FloatRegister s1, FloatRegister s2, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(faligndata_op3) | fs1(s1, FloatRegisterImpl::D) | opf(faligndata_opf) | fs2(s2, FloatRegisterImpl::D)); } +inline void Assembler::faligndata(FloatRegister s1, FloatRegister s2, FloatRegister d) { + vis1_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(faligndata_op3) | fs1(s1, FloatRegisterImpl::D) | opf(faligndata_opf) | fs2(s2, FloatRegisterImpl::D)); +} -inline void Assembler::fzero( FloatRegisterImpl::Width w, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fzero_op3) | opf(0x62 - w)); } +inline void Assembler::fzero(FloatRegisterImpl::Width w, FloatRegister d) { + vis1_only(); + emit_int32(op(arith_op) | fd(d, w) | op3(fzero_op3) | opf(0x62 - w)); +} -inline void Assembler::fsrc2( FloatRegisterImpl::Width w, FloatRegister s2, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fsrc_op3) | opf(0x7A - w) | fs2(s2, w)); } +inline void Assembler::fsrc2(FloatRegisterImpl::Width w, FloatRegister s2, FloatRegister d) { + vis1_only(); + emit_int32(op(arith_op) | fd(d, w) | op3(fsrc_op3) | opf(0x7A - w) | fs2(s2, w)); +} -inline void Assembler::fnot1( FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, w) | op3(fnot_op3) | fs1(s1, w) | opf(0x6C - w)); } +inline void Assembler::fnot1(FloatRegisterImpl::Width w, FloatRegister s1, FloatRegister d) { + vis1_only(); + emit_int32(op(arith_op) | fd(d, w) | op3(fnot_op3) | fs1(s1, w) | opf(0x6C - w)); +} -inline void Assembler::fpmerge( FloatRegister s1, FloatRegister s2, FloatRegister d ) { vis1_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(0x36) | fs1(s1, FloatRegisterImpl::S) | opf(0x4b) | fs2(s2, FloatRegisterImpl::S)); } +inline void Assembler::fpmerge(FloatRegister s1, FloatRegister s2, FloatRegister d) { + vis1_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(0x36) | fs1(s1, FloatRegisterImpl::S) | opf(0x4b) | fs2(s2, FloatRegisterImpl::S)); +} -inline void Assembler::stpartialf( Register s1, Register s2, FloatRegister d, int ia ) { vis1_only(); emit_int32( op(ldst_op) | fd(d, FloatRegisterImpl::D) | op3(stpartialf_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); } +inline void Assembler::stpartialf(Register s1, Register s2, FloatRegister d, int ia) { + vis1_only(); + emit_int32(op(ldst_op) | fd(d, FloatRegisterImpl::D) | op3(stpartialf_op3) | rs1(s1) | imm_asi(ia) | rs2(s2)); +} -// VIS2 instructions +// VIS2 instructions -inline void Assembler::edge8n( Register s1, Register s2, Register d ) { vis2_only(); emit_int32( op(arith_op) | rd(d) | op3(edge_op3) | rs1(s1) | opf(edge8n_opf) | rs2(s2)); } +inline void Assembler::edge8n(Register s1, Register s2, Register d) { + vis2_only(); + emit_int32(op(arith_op) | rd(d) | op3(edge_op3) | rs1(s1) | opf(edge8n_opf) | rs2(s2)); +} -inline void Assembler::bmask( Register s1, Register s2, Register d ) { vis2_only(); emit_int32( op(arith_op) | rd(d) | op3(bmask_op3) | rs1(s1) | opf(bmask_opf) | rs2(s2)); } -inline void Assembler::bshuffle( FloatRegister s1, FloatRegister s2, FloatRegister d ) { vis2_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(bshuffle_op3) | fs1(s1, FloatRegisterImpl::D) | opf(bshuffle_opf) | fs2(s2, FloatRegisterImpl::D)); } +inline void Assembler::bmask(Register s1, Register s2, Register d) { + vis2_only(); + emit_int32(op(arith_op) | rd(d) | op3(bmask_op3) | rs1(s1) | opf(bmask_opf) | rs2(s2)); +} +inline void Assembler::bshuffle(FloatRegister s1, FloatRegister s2, FloatRegister d) { + vis2_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(bshuffle_op3) | fs1(s1, FloatRegisterImpl::D) | opf(bshuffle_opf) | fs2(s2, FloatRegisterImpl::D)); +} // VIS3 instructions -inline void Assembler::movstosw( FloatRegister s, Register d ) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstosw_opf) | fs2(s, FloatRegisterImpl::S)); } -inline void Assembler::movstouw( FloatRegister s, Register d ) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstouw_opf) | fs2(s, FloatRegisterImpl::S)); } -inline void Assembler::movdtox( FloatRegister s, Register d ) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mdtox_opf) | fs2(s, FloatRegisterImpl::D)); } +inline void Assembler::movstosw(FloatRegister s, Register d) { + vis3_only(); + emit_int32(op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstosw_opf) | fs2(s, FloatRegisterImpl::S)); +} +inline void Assembler::movstouw(FloatRegister s, Register d) { + vis3_only(); + emit_int32(op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstouw_opf) | fs2(s, FloatRegisterImpl::S)); +} +inline void Assembler::movdtox(FloatRegister s, Register d) { + vis3_only(); + emit_int32(op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mdtox_opf) | fs2(s, FloatRegisterImpl::D)); +} -inline void Assembler::movwtos( Register s, FloatRegister d ) { vis3_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(mftoi_op3) | opf(mwtos_opf) | rs2(s)); } -inline void Assembler::movxtod( Register s, FloatRegister d ) { vis3_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(mftoi_op3) | opf(mxtod_opf) | rs2(s)); } +inline void Assembler::movwtos(Register s, FloatRegister d) { + vis3_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(mftoi_op3) | opf(mwtos_opf) | rs2(s)); +} +inline void Assembler::movxtod(Register s, FloatRegister d) { + vis3_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(mftoi_op3) | opf(mxtod_opf) | rs2(s)); +} -inline void Assembler::xmulx(Register s1, Register s2, Register d) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(xmulx_op3) | rs1(s1) | opf(xmulx_opf) | rs2(s2)); } -inline void Assembler::xmulxhi(Register s1, Register s2, Register d) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(xmulx_op3) | rs1(s1) | opf(xmulxhi_opf) | rs2(s2)); } +inline void Assembler::xmulx(Register s1, Register s2, Register d) { + vis3_only(); + emit_int32(op(arith_op) | rd(d) | op3(xmulx_op3) | rs1(s1) | opf(xmulx_opf) | rs2(s2)); +} +inline void Assembler::xmulxhi(Register s1, Register s2, Register d) { + vis3_only(); + emit_int32(op(arith_op) | rd(d) | op3(xmulx_op3) | rs1(s1) | opf(xmulxhi_opf) | rs2(s2)); +} // Crypto SHA instructions -inline void Assembler::sha1() { sha1_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha1_opf)); } -inline void Assembler::sha256() { sha256_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha256_opf)); } -inline void Assembler::sha512() { sha512_only(); emit_int32( op(arith_op) | op3(sha_op3) | opf(sha512_opf)); } +inline void Assembler::sha1() { + sha1_only(); + emit_int32(op(arith_op) | op3(sha_op3) | opf(sha1_opf)); +} +inline void Assembler::sha256() { + sha256_only(); + emit_int32(op(arith_op) | op3(sha_op3) | opf(sha256_opf)); +} +inline void Assembler::sha512() { + sha512_only(); + emit_int32(op(arith_op) | op3(sha_op3) | opf(sha512_opf)); +} // CRC32C instruction -inline void Assembler::crc32c( FloatRegister s1, FloatRegister s2, FloatRegister d ) { crc32c_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(crc32c_op3) | fs1(s1, FloatRegisterImpl::D) | opf(crc32c_opf) | fs2(s2, FloatRegisterImpl::D)); } +inline void Assembler::crc32c(FloatRegister s1, FloatRegister s2, FloatRegister d) { + crc32c_only(); + emit_int32(op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(crc32c_op3) | fs1(s1, FloatRegisterImpl::D) | opf(crc32c_opf) | fs2(s2, FloatRegisterImpl::D)); +} #endif // CPU_SPARC_VM_ASSEMBLER_SPARC_INLINE_HPP diff --git a/hotspot/src/cpu/sparc/vm/bytes_sparc.hpp b/hotspot/src/cpu/sparc/vm/bytes_sparc.hpp index 67d4307ff74..0ce1f5fac48 100644 --- a/hotspot/src/cpu/sparc/vm/bytes_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/bytes_sparc.hpp @@ -34,10 +34,6 @@ class Bytes: AllStatic { // can I count on address always being a pointer to an unsigned char? Yes - // Returns true, if the byte ordering used by Java is different from the nativ byte ordering - // of the underlying machine. For example, true for Intel x86, False, for Solaris on Sparc. - static inline bool is_Java_byte_ordering_different() { return false; } - // Thus, a swap between native and Java ordering is always a no-op: static inline u2 swap_u2(u2 x) { return x; } static inline u4 swap_u4(u4 x) { return x; } diff --git a/hotspot/src/cpu/sparc/vm/c1_FpuStackSim_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_FpuStackSim_sparc.cpp index 8c3a19a9e78..abaf500ebd7 100644 --- a/hotspot/src/cpu/sparc/vm/c1_FpuStackSim_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_FpuStackSim_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -22,10 +22,4 @@ * */ -#include "precompiled.hpp" -#include "c1/c1_FpuStackSim.hpp" -#include "c1/c1_FrameMap.hpp" -#include "utilities/array.hpp" -#include "utilities/ostream.hpp" - // No FPU stack on SPARC diff --git a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp index ae4262bb73b..71e6276f09c 100644 --- a/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c1_FrameMap_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -159,21 +159,12 @@ public: -#ifdef _LP64 static LIR_Opr as_long_opr(Register r) { return as_long_single_opr(r); } static LIR_Opr as_pointer_opr(Register r) { return as_long_single_opr(r); } -#else - static LIR_Opr as_long_opr(Register r) { - return as_long_pair_opr(r); - } - static LIR_Opr as_pointer_opr(Register r) { - return as_opr(r); - } -#endif static LIR_Opr as_float_opr(FloatRegister r) { return LIR_OprFact::single_fpu(r->encoding()); } diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index ae2942f19b5..5269c9fd8be 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -440,6 +440,31 @@ void LIR_Assembler::klass2reg_with_patching(Register reg, CodeEmitInfo *info) { } void LIR_Assembler::emit_op3(LIR_Op3* op) { + switch (op->code()) { + case lir_idiv: + case lir_irem: // Both idiv & irem are handled after the switch (below). + break; + case lir_fmaf: + __ fmadd(FloatRegisterImpl::S, + op->in_opr1()->as_float_reg(), + op->in_opr2()->as_float_reg(), + op->in_opr3()->as_float_reg(), + op->result_opr()->as_float_reg()); + return; + case lir_fmad: + __ fmadd(FloatRegisterImpl::D, + op->in_opr1()->as_double_reg(), + op->in_opr2()->as_double_reg(), + op->in_opr3()->as_double_reg(), + op->result_opr()->as_double_reg()); + return; + default: + ShouldNotReachHere(); + break; + } + + // Handle idiv & irem: + Register Rdividend = op->in_opr1()->as_register(); Register Rdivisor = noreg; Register Rscratch = op->in_opr3()->as_register(); @@ -556,11 +581,9 @@ void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) { // guarantee that 32-bit loads always sign extended but that isn't // true and since sign extension isn't free, it would impose a // slight cost. -#ifdef _LP64 if (op->type() == T_INT) { __ br(acond, false, Assembler::pn, *(op->label())); } else -#endif __ brx(acond, false, Assembler::pn, *(op->label())); } // The peephole pass fills the delay slot @@ -576,12 +599,7 @@ void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { Register rlo = dst->as_register_lo(); Register rhi = dst->as_register_hi(); Register rval = op->in_opr()->as_register(); -#ifdef _LP64 __ sra(rval, 0, rlo); -#else - __ mov(rval, rlo); - __ sra(rval, BitsPerInt-1, rhi); -#endif break; } case Bytecodes::_i2d: @@ -614,11 +632,7 @@ void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { Register rlo = op->in_opr()->as_register_lo(); Register rhi = op->in_opr()->as_register_hi(); Register rdst = dst->as_register(); -#ifdef _LP64 __ sra(rlo, 0, rdst); -#else - __ mov(rlo, rdst); -#endif break; } case Bytecodes::_d2f: @@ -711,7 +725,6 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType case T_SHORT : __ sth(from_reg->as_register(), base, offset); break; case T_INT : __ stw(from_reg->as_register(), base, offset); break; case T_LONG : -#ifdef _LP64 if (unaligned || PatchALot) { // Don't use O7 here because it may be equal to 'base' (see LIR_Assembler::reg2mem) assert(G3_scratch != base, "can't handle this"); @@ -722,11 +735,6 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, int offset, BasicType } else { __ stx(from_reg->as_register_lo(), base, offset); } -#else - assert(Assembler::is_simm13(offset + 4), "must be"); - __ stw(from_reg->as_register_lo(), base, offset + lo_word_offset_in_bytes); - __ stw(from_reg->as_register_hi(), base, offset + hi_word_offset_in_bytes); -#endif break; case T_ADDRESS: case T_METADATA: @@ -778,12 +786,7 @@ int LIR_Assembler::store(LIR_Opr from_reg, Register base, Register disp, BasicTy case T_SHORT : __ sth(from_reg->as_register(), base, disp); break; case T_INT : __ stw(from_reg->as_register(), base, disp); break; case T_LONG : -#ifdef _LP64 __ stx(from_reg->as_register_lo(), base, disp); -#else - assert(from_reg->as_register_hi()->successor() == from_reg->as_register_lo(), "must match"); - __ std(from_reg->as_register_hi(), base, disp); -#endif break; case T_ADDRESS: __ st_ptr(from_reg->as_register(), base, disp); @@ -826,40 +829,22 @@ int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType typ case T_INT : __ ld(base, offset, to_reg->as_register()); break; case T_LONG : if (!unaligned && !PatchALot) { -#ifdef _LP64 __ ldx(base, offset, to_reg->as_register_lo()); -#else - assert(to_reg->as_register_hi()->successor() == to_reg->as_register_lo(), - "must be sequential"); - __ ldd(base, offset, to_reg->as_register_hi()); -#endif } else { -#ifdef _LP64 assert(base != to_reg->as_register_lo(), "can't handle this"); assert(O7 != to_reg->as_register_lo(), "can't handle this"); __ ld(base, offset + hi_word_offset_in_bytes, to_reg->as_register_lo()); __ lduw(base, offset + lo_word_offset_in_bytes, O7); // in case O7 is base or offset, use it last __ sllx(to_reg->as_register_lo(), 32, to_reg->as_register_lo()); __ or3(to_reg->as_register_lo(), O7, to_reg->as_register_lo()); -#else - if (base == to_reg->as_register_lo()) { - __ ld(base, offset + hi_word_offset_in_bytes, to_reg->as_register_hi()); - __ ld(base, offset + lo_word_offset_in_bytes, to_reg->as_register_lo()); - } else { - __ ld(base, offset + lo_word_offset_in_bytes, to_reg->as_register_lo()); - __ ld(base, offset + hi_word_offset_in_bytes, to_reg->as_register_hi()); - } -#endif } break; case T_METADATA: __ ld_ptr(base, offset, to_reg->as_register()); break; case T_ADDRESS: -#ifdef _LP64 if (offset == oopDesc::klass_offset_in_bytes() && UseCompressedClassPointers) { __ lduw(base, offset, to_reg->as_register()); __ decode_klass_not_null(to_reg->as_register()); } else -#endif { __ ld_ptr(base, offset, to_reg->as_register()); } @@ -921,13 +906,7 @@ int LIR_Assembler::load(Register base, Register disp, LIR_Opr to_reg, BasicType case T_FLOAT: __ ldf(FloatRegisterImpl::S, base, disp, to_reg->as_float_reg()); break; case T_DOUBLE: __ ldf(FloatRegisterImpl::D, base, disp, to_reg->as_double_reg()); break; case T_LONG : -#ifdef _LP64 __ ldx(base, disp, to_reg->as_register_lo()); -#else - assert(to_reg->as_register_hi()->successor() == to_reg->as_register_lo(), - "must be sequential"); - __ ldd(base, disp, to_reg->as_register_hi()); -#endif break; default : ShouldNotReachHere(); } @@ -1107,16 +1086,9 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod jlong con = c->as_jlong(); if (to_reg->is_double_cpu()) { -#ifdef _LP64 __ set(con, to_reg->as_register_lo()); -#else - __ set(low(con), to_reg->as_register_lo()); - __ set(high(con), to_reg->as_register_hi()); -#endif -#ifdef _LP64 } else if (to_reg->is_single_cpu()) { __ set(con, to_reg->as_register()); -#endif } else { ShouldNotReachHere(); assert(to_reg->is_double_fpu(), "wrong register kind"); @@ -1190,12 +1162,7 @@ void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_cod __ ldf (FloatRegisterImpl::D, O7, const_addrlit.low10(), to_reg->as_double_reg()); } else { assert(to_reg->is_double_cpu(), "Must be a long register."); -#ifdef _LP64 __ set(jlong_cast(c->as_jdouble()), to_reg->as_register_lo()); -#else - __ set(low(jlong_cast(c->as_jdouble())), to_reg->as_register_lo()); - __ set(high(jlong_cast(c->as_jdouble())), to_reg->as_register_hi()); -#endif } } @@ -1366,22 +1333,10 @@ void LIR_Assembler::reg2reg(LIR_Opr from_reg, LIR_Opr to_reg) { } } else if (!from_reg->is_float_kind() && !to_reg->is_float_kind()) { if (from_reg->is_double_cpu()) { -#ifdef _LP64 __ mov(from_reg->as_pointer_register(), to_reg->as_pointer_register()); -#else - assert(to_reg->is_double_cpu() && - from_reg->as_register_hi() != to_reg->as_register_lo() && - from_reg->as_register_lo() != to_reg->as_register_hi(), - "should both be long and not overlap"); - // long to long moves - __ mov(from_reg->as_register_hi(), to_reg->as_register_hi()); - __ mov(from_reg->as_register_lo(), to_reg->as_register_lo()); -#endif -#ifdef _LP64 } else if (to_reg->is_double_cpu()) { // int to int moves __ mov(from_reg->as_register(), to_reg->as_register_lo()); -#endif } else { // int to int moves __ mov(from_reg->as_register(), to_reg->as_register()); @@ -1460,21 +1415,6 @@ void LIR_Assembler::return_op(LIR_Opr result) { if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) { __ reserved_stack_check(); } - // the poll may need a register so just pick one that isn't the return register -#if defined(TIERED) && !defined(_LP64) - if (result->type_field() == LIR_OprDesc::long_type) { - // Must move the result to G1 - // Must leave proper result in O0,O1 and G1 (TIERED only) - __ sllx(I0, 32, G1); // Shift bits into high G1 - __ srl (I1, 0, I1); // Zero extend O1 (harmless?) - __ or3 (I1, G1, G1); // OR 64 bits into G1 -#ifdef ASSERT - // mangle it so any problems will show up - __ set(0xdeadbeef, I0); - __ set(0xdeadbeef, I1); -#endif - } -#endif // TIERED __ set((intptr_t)os::get_polling_page(), L0); __ relocate(relocInfo::poll_return_type); __ ld_ptr(L0, 0, G0); @@ -1568,23 +1508,11 @@ void LIR_Assembler::comp_op(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, Register xhi = opr1->as_register_hi(); if (opr2->is_constant() && opr2->as_jlong() == 0) { assert(condition == lir_cond_equal || condition == lir_cond_notEqual, "only handles these cases"); -#ifdef _LP64 __ orcc(xhi, G0, G0); -#else - __ orcc(xhi, xlo, G0); -#endif } else if (opr2->is_register()) { Register ylo = opr2->as_register_lo(); Register yhi = opr2->as_register_hi(); -#ifdef _LP64 __ cmp(xlo, ylo); -#else - __ subcc(xlo, ylo, xlo); - __ subccc(xhi, yhi, xhi); - if (condition == lir_cond_equal || condition == lir_cond_notEqual) { - __ orcc(xhi, xlo, G0); - } -#endif } else { ShouldNotReachHere(); } @@ -1612,13 +1540,7 @@ void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Op ShouldNotReachHere(); } } else if (code == lir_cmp_l2i) { -#ifdef _LP64 __ lcmp(left->as_register_lo(), right->as_register_lo(), dst->as_register()); -#else - __ lcmp(left->as_register_hi(), left->as_register_lo(), - right->as_register_hi(), right->as_register_lo(), - dst->as_register()); -#endif } else { ShouldNotReachHere(); } @@ -1656,12 +1578,11 @@ void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, L ShouldNotReachHere(); } Label skip; -#ifdef _LP64 if (type == T_INT) { __ br(acond, false, Assembler::pt, skip); - } else -#endif + } else { __ brx(acond, false, Assembler::pt, skip); // checks icc on 32bit and xcc on 64bit + } if (opr1->is_constant() && opr1->type() == T_INT) { Register dest = result->as_register(); if (Assembler::is_simm13(opr1->as_jint())) { @@ -1720,7 +1641,6 @@ void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr } } else if (dest->is_double_cpu()) { -#ifdef _LP64 Register dst_lo = dest->as_register_lo(); Register op1_lo = left->as_pointer_register(); Register op2_lo = right->as_pointer_register(); @@ -1736,28 +1656,6 @@ void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr default: ShouldNotReachHere(); } -#else - Register op1_lo = left->as_register_lo(); - Register op1_hi = left->as_register_hi(); - Register op2_lo = right->as_register_lo(); - Register op2_hi = right->as_register_hi(); - Register dst_lo = dest->as_register_lo(); - Register dst_hi = dest->as_register_hi(); - - switch (code) { - case lir_add: - __ addcc(op1_lo, op2_lo, dst_lo); - __ addc (op1_hi, op2_hi, dst_hi); - break; - - case lir_sub: - __ subcc(op1_lo, op2_lo, dst_lo); - __ subc (op1_hi, op2_hi, dst_hi); - break; - - default: ShouldNotReachHere(); - } -#endif } else { assert (right->is_single_cpu(), "Just Checking"); @@ -1852,23 +1750,14 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr int simm13 = (int)c; switch (code) { case lir_logic_and: -#ifndef _LP64 - __ and3 (left->as_register_hi(), 0, dest->as_register_hi()); -#endif __ and3 (left->as_register_lo(), simm13, dest->as_register_lo()); break; case lir_logic_or: -#ifndef _LP64 - __ or3 (left->as_register_hi(), 0, dest->as_register_hi()); -#endif __ or3 (left->as_register_lo(), simm13, dest->as_register_lo()); break; case lir_logic_xor: -#ifndef _LP64 - __ xor3 (left->as_register_hi(), 0, dest->as_register_hi()); -#endif __ xor3 (left->as_register_lo(), simm13, dest->as_register_lo()); break; @@ -1886,7 +1775,6 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr default: ShouldNotReachHere(); } } else { -#ifdef _LP64 Register l = (left->is_single_cpu() && left->is_oop_register()) ? left->as_register() : left->as_register_lo(); Register r = (right->is_single_cpu() && right->is_oop_register()) ? right->as_register() : @@ -1898,26 +1786,6 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr case lir_logic_xor: __ xor3 (l, r, dest->as_register_lo()); break; default: ShouldNotReachHere(); } -#else - switch (code) { - case lir_logic_and: - __ and3 (left->as_register_hi(), right->as_register_hi(), dest->as_register_hi()); - __ and3 (left->as_register_lo(), right->as_register_lo(), dest->as_register_lo()); - break; - - case lir_logic_or: - __ or3 (left->as_register_hi(), right->as_register_hi(), dest->as_register_hi()); - __ or3 (left->as_register_lo(), right->as_register_lo(), dest->as_register_lo()); - break; - - case lir_logic_xor: - __ xor3 (left->as_register_hi(), right->as_register_hi(), dest->as_register_hi()); - __ xor3 (left->as_register_lo(), right->as_register_lo(), dest->as_register_lo()); - break; - - default: ShouldNotReachHere(); - } -#endif } } } @@ -1975,12 +1843,10 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { BasicType basic_type = default_type != NULL ? default_type->element_type()->basic_type() : T_ILLEGAL; if (basic_type == T_ARRAY) basic_type = T_OBJECT; -#ifdef _LP64 // higher 32bits must be null __ sra(dst_pos, 0, dst_pos); __ sra(src_pos, 0, src_pos); __ sra(length, 0, length); -#endif // set up the arraycopy stub information ArrayCopyStub* stub = op->stub(); @@ -2316,7 +2182,6 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, LIR_Opr count, LIR_Opr dest, LIR_Opr tmp) { if (dest->is_single_cpu()) { -#ifdef _LP64 if (left->type() == T_OBJECT) { switch (code) { case lir_shl: __ sllx (left->as_register(), count->as_register(), dest->as_register()); break; @@ -2325,7 +2190,6 @@ void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, LIR_Opr count, LIR_Opr default: ShouldNotReachHere(); } } else -#endif switch (code) { case lir_shl: __ sll (left->as_register(), count->as_register(), dest->as_register()); break; case lir_shr: __ sra (left->as_register(), count->as_register(), dest->as_register()); break; @@ -2333,27 +2197,17 @@ void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, LIR_Opr count, LIR_Opr default: ShouldNotReachHere(); } } else { -#ifdef _LP64 switch (code) { case lir_shl: __ sllx (left->as_register_lo(), count->as_register(), dest->as_register_lo()); break; case lir_shr: __ srax (left->as_register_lo(), count->as_register(), dest->as_register_lo()); break; case lir_ushr: __ srlx (left->as_register_lo(), count->as_register(), dest->as_register_lo()); break; default: ShouldNotReachHere(); } -#else - switch (code) { - case lir_shl: __ lshl (left->as_register_hi(), left->as_register_lo(), count->as_register(), dest->as_register_hi(), dest->as_register_lo(), G3_scratch); break; - case lir_shr: __ lshr (left->as_register_hi(), left->as_register_lo(), count->as_register(), dest->as_register_hi(), dest->as_register_lo(), G3_scratch); break; - case lir_ushr: __ lushr (left->as_register_hi(), left->as_register_lo(), count->as_register(), dest->as_register_hi(), dest->as_register_lo(), G3_scratch); break; - default: ShouldNotReachHere(); - } -#endif } } void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, jint count, LIR_Opr dest) { -#ifdef _LP64 if (left->type() == T_OBJECT) { count = count & 63; // shouldn't shift by more than sizeof(intptr_t) Register l = left->as_register(); @@ -2366,7 +2220,6 @@ void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, jint count, LIR_Opr de } return; } -#endif if (dest->is_single_cpu()) { count = count & 0x1F; // Java spec @@ -2425,7 +2278,7 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { op->tmp4()->as_register() == O1 && op->klass()->as_register() == G5, "must be"); - LP64_ONLY( __ signx(op->len()->as_register()); ) + __ signx(op->len()->as_register()); if (UseSlowPath || (!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) || (!UseFastNewTypeArray && (op->type() != T_OBJECT && op->type() != T_ARRAY))) { @@ -2748,7 +2601,6 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { Register new_value_hi = op->new_value()->as_register_hi(); Register t1 = op->tmp1()->as_register(); Register t2 = op->tmp2()->as_register(); -#ifdef _LP64 __ mov(cmp_value_lo, t1); __ mov(new_value_lo, t2); // perform the compare and swap operation @@ -2756,23 +2608,6 @@ void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { // generate condition code - if the swap succeeded, t2 ("new value" reg) was // overwritten with the original value in "addr" and will be equal to t1. __ cmp(t1, t2); -#else - // move high and low halves of long values into single registers - __ sllx(cmp_value_hi, 32, t1); // shift high half into temp reg - __ srl(cmp_value_lo, 0, cmp_value_lo); // clear upper 32 bits of low half - __ or3(t1, cmp_value_lo, t1); // t1 holds 64-bit compare value - __ sllx(new_value_hi, 32, t2); - __ srl(new_value_lo, 0, new_value_lo); - __ or3(t2, new_value_lo, t2); // t2 holds 64-bit value to swap - // perform the compare and swap operation - __ casx(addr, t1, t2); - // generate condition code - if the swap succeeded, t2 ("new value" reg) was - // overwritten with the original value in "addr" and will be equal to t1. - // Produce icc flag for 32bit. - __ sub(t1, t2, t2); - __ srlx(t2, 32, t1); - __ orcc(t2, t1, G0); -#endif } else if (op->code() == lir_cas_int || op->code() == lir_cas_obj) { Register addr = op->addr()->as_pointer_register(); Register cmp_value = op->cmp_value()->as_register(); @@ -2914,13 +2749,8 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { assert(data->is_CounterData(), "need CounterData for calls"); assert(op->mdo()->is_single_cpu(), "mdo must be allocated"); Register mdo = op->mdo()->as_register(); -#ifdef _LP64 assert(op->tmp1()->is_double_cpu(), "tmp1 must be allocated"); Register tmp1 = op->tmp1()->as_register_lo(); -#else - assert(op->tmp1()->is_single_cpu(), "tmp1 must be allocated"); - Register tmp1 = op->tmp1()->as_register(); -#endif metadata2reg(md->constant_encoding(), mdo); int mdo_offset_bias = 0; if (!Assembler::is_simm13(md->byte_offset_of_slot(data, CounterData::count_offset()) + @@ -3200,12 +3030,7 @@ void LIR_Assembler::negate(LIR_Opr left, LIR_Opr dest) { assert (left->is_double_cpu(), "Must be a long"); Register Rlow = left->as_register_lo(); Register Rhi = left->as_register_hi(); -#ifdef _LP64 __ sub(G0, Rlow, dest->as_register_lo()); -#else - __ subcc(G0, Rlow, dest->as_register_lo()); - __ subc (G0, Rhi, dest->as_register_hi()); -#endif } } @@ -3245,9 +3070,7 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest, void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) { -#ifdef _LP64 ShouldNotReachHere(); -#endif NEEDS_CLEANUP; if (type == T_LONG) { @@ -3366,16 +3189,29 @@ void LIR_Assembler::unpack64(LIR_Opr src, LIR_Opr dst) { __ srl (rs, 0, rd->successor()); } - void LIR_Assembler::leal(LIR_Opr addr_opr, LIR_Opr dest) { - LIR_Address* addr = addr_opr->as_address_ptr(); - assert(addr->index()->is_illegal() && addr->scale() == LIR_Address::times_1, "can't handle complex addresses yet"); + const LIR_Address* addr = addr_opr->as_address_ptr(); + assert(addr->scale() == LIR_Address::times_1, "can't handle complex addresses yet"); + const Register dest_reg = dest->as_pointer_register(); + const Register base_reg = addr->base()->as_pointer_register(); if (Assembler::is_simm13(addr->disp())) { - __ add(addr->base()->as_pointer_register(), addr->disp(), dest->as_pointer_register()); + if (addr->index()->is_valid()) { + const Register index_reg = addr->index()->as_pointer_register(); + assert(index_reg != G3_scratch, "invariant"); + __ add(base_reg, addr->disp(), G3_scratch); + __ add(index_reg, G3_scratch, dest_reg); + } else { + __ add(base_reg, addr->disp(), dest_reg); + } } else { __ set(addr->disp(), G3_scratch); - __ add(addr->base()->as_pointer_register(), G3_scratch, dest->as_pointer_register()); + if (addr->index()->is_valid()) { + const Register index_reg = addr->index()->as_pointer_register(); + assert(index_reg != G3_scratch, "invariant"); + __ add(index_reg, G3_scratch, G3_scratch); + } + __ add(base_reg, G3_scratch, dest_reg); } } @@ -3491,31 +3327,6 @@ void LIR_Assembler::peephole(LIR_List* lir) { inst->insert_before(i + 1, delay_op); i++; } - -#if defined(TIERED) && !defined(_LP64) - // fixup the return value from G1 to O0/O1 for long returns. - // It's done here instead of in LIRGenerator because there's - // such a mismatch between the single reg and double reg - // calling convention. - LIR_OpJavaCall* callop = op->as_OpJavaCall(); - if (callop->result_opr() == FrameMap::out_long_opr) { - LIR_OpJavaCall* call; - LIR_OprList* arguments = new LIR_OprList(callop->arguments()->length()); - for (int a = 0; a < arguments->length(); a++) { - arguments[a] = callop->arguments()[a]; - } - if (op->code() == lir_virtual_call) { - call = new LIR_OpJavaCall(op->code(), callop->method(), callop->receiver(), FrameMap::g1_long_single_opr, - callop->vtable_offset(), arguments, callop->info()); - } else { - call = new LIR_OpJavaCall(op->code(), callop->method(), callop->receiver(), FrameMap::g1_long_single_opr, - callop->addr(), arguments, callop->info()); - } - inst->at_put(i - 1, call); - inst->insert_before(i + 1, new LIR_Op1(lir_unpack64, FrameMap::g1_long_single_opr, callop->result_opr(), - T_LONG, lir_patch_none, NULL)); - } -#endif break; } } @@ -3533,14 +3344,10 @@ void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr } else if (data->is_oop()) { Register obj = data->as_register(); Register narrow = tmp->as_register(); -#ifdef _LP64 assert(UseCompressedOops, "swap is 32bit only"); __ encode_heap_oop(obj, narrow); __ swap(as_Address(addr), narrow); __ decode_heap_oop(narrow, obj); -#else - __ swap(as_Address(addr), obj); -#endif } else { ShouldNotReachHere(); } diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp index c46d0002af3..37a3b38cfb3 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -61,11 +61,7 @@ ciMethodData*& md, ciProfileData*& data, int& mdo_offset_bias); enum { -#ifdef _LP64 _call_stub_size = 68, -#else - _call_stub_size = 20, -#endif // _LP64 _call_aot_stub_size = 0, _exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(128), _deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(64) diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp index 069b9a2f46e..28f04a9c96e 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -70,7 +70,7 @@ LIR_Opr LIRGenerator::exceptionOopOpr() { return FrameMap::Oexcepti LIR_Opr LIRGenerator::exceptionPcOpr() { return FrameMap::Oissuing_pc_opr; } LIR_Opr LIRGenerator::syncLockOpr() { return new_register(T_INT); } LIR_Opr LIRGenerator::syncTempOpr() { return new_register(T_OBJECT); } -LIR_Opr LIRGenerator::getThreadTemp() { return rlock_callee_saved(NOT_LP64(T_INT) LP64_ONLY(T_LONG)); } +LIR_Opr LIRGenerator::getThreadTemp() { return rlock_callee_saved(T_LONG); } LIR_Opr LIRGenerator::result_register_for(ValueType* type, bool callee) { LIR_Opr opr; @@ -215,13 +215,11 @@ LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_o } } } else { -#ifdef _LP64 if (index_opr->type() == T_INT) { LIR_Opr tmp = new_register(T_LONG); __ convert(Bytecodes::_i2l, index_opr, tmp); index_opr = tmp; } -#endif base_opr = new_pointer_register(); assert (index_opr->is_register(), "Must be register"); @@ -955,7 +953,29 @@ void LIRGenerator::do_update_CRC32C(Intrinsic* x) { } void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) { - fatal("FMA intrinsic is not implemented on this platform"); + assert(x->number_of_arguments() == 3, "wrong type"); + assert(UseFMA, "Needs FMA instructions support."); + + LIRItem a(x->argument_at(0), this); + LIRItem b(x->argument_at(1), this); + LIRItem c(x->argument_at(2), this); + + a.load_item(); + b.load_item(); + c.load_item(); + + LIR_Opr ina = a.result(); + LIR_Opr inb = b.result(); + LIR_Opr inc = c.result(); + LIR_Opr res = rlock_result(x); + + switch (x->id()) { + case vmIntrinsics::_fmaF: __ fmaf(ina, inb, inc, res); break; + case vmIntrinsics::_fmaD: __ fmad(ina, inb, inc, res); break; + default: + ShouldNotReachHere(); + break; + } } void LIRGenerator::do_vectorizedMismatch(Intrinsic* x) { @@ -1317,20 +1337,12 @@ void LIRGenerator::trace_block_entry(BlockBegin* block) { void LIRGenerator::volatile_field_store(LIR_Opr value, LIR_Address* address, CodeEmitInfo* info) { -#ifdef _LP64 __ store(value, address, info); -#else - __ volatile_store_mem_reg(value, address, info); -#endif } void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result, CodeEmitInfo* info) { -#ifdef _LP64 __ load(address, result, info); -#else - __ volatile_load_mem_reg(address, result, info); -#endif } @@ -1340,11 +1352,6 @@ void LIRGenerator::put_Object_unsafe(LIR_Opr src, LIR_Opr offset, LIR_Opr data, LIR_Opr index_op = offset; bool is_obj = (type == T_ARRAY || type == T_OBJECT); -#ifndef _LP64 - if (is_volatile && type == T_LONG) { - __ volatile_store_unsafe_reg(data, src, offset, type, NULL, lir_patch_none); - } else -#endif { if (type == T_BOOLEAN) { type = T_BYTE; @@ -1374,11 +1381,6 @@ void LIRGenerator::put_Object_unsafe(LIR_Opr src, LIR_Opr offset, LIR_Opr data, void LIRGenerator::get_Object_unsafe(LIR_Opr dst, LIR_Opr src, LIR_Opr offset, BasicType type, bool is_volatile) { -#ifndef _LP64 - if (is_volatile && type == T_LONG) { - __ volatile_load_unsafe_reg(src, offset, dst, type, NULL, lir_patch_none); - } else -#endif { LIR_Address* addr = new LIR_Address(src, offset, type); __ load(addr, dst); @@ -1403,17 +1405,13 @@ void LIRGenerator::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) { // Because we want a 2-arg form of xchg __ move(data, dst); - assert (!x->is_add() && (type == T_INT || (is_obj LP64_ONLY(&& UseCompressedOops))), "unexpected type"); + assert (!x->is_add() && (type == T_INT || (is_obj && UseCompressedOops)), "unexpected type"); LIR_Address* addr; if (offset->is_constant()) { -#ifdef _LP64 jlong l = offset->as_jlong(); assert((jlong)((jint)l) == l, "offset too large for constant"); jint c = (jint)l; -#else - jint c = offset->as_jint(); -#endif addr = new LIR_Address(src.result(), c, type); } else { addr = new LIR_Address(src.result(), offset, type); diff --git a/hotspot/src/cpu/sparc/vm/c1_LIR_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIR_sparc.cpp index e9467760679..c21d2c1d9ad 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIR_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIR_sparc.cpp @@ -48,16 +48,9 @@ LIR_Opr LIR_OprFact::double_fpu(int reg1, int reg2) { void LIR_Address::verify() const { assert(scale() == times_1, "Scaled addressing mode not available on SPARC and should not be used"); assert(disp() == 0 || index()->is_illegal(), "can't have both"); -#ifdef _LP64 assert(base()->is_cpu_register(), "wrong base operand"); assert(index()->is_illegal() || index()->is_double_cpu(), "wrong index operand"); assert(base()->type() == T_OBJECT || base()->type() == T_LONG || base()->type() == T_METADATA, "wrong type for addresses"); -#else - assert(base()->is_single_cpu(), "wrong base operand"); - assert(index()->is_illegal() || index()->is_single_cpu(), "wrong index operand"); - assert(base()->type() == T_OBJECT || base()->type() == T_INT || base()->type() == T_METADATA, - "wrong type for addresses"); -#endif } #endif // PRODUCT diff --git a/hotspot/src/cpu/sparc/vm/c1_LinearScan_sparc.hpp b/hotspot/src/cpu/sparc/vm/c1_LinearScan_sparc.hpp index 164c000de21..6656056bb6f 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LinearScan_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c1_LinearScan_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -32,11 +32,7 @@ inline bool LinearScan::is_processed_reg_num(int reg_num) { inline int LinearScan::num_physical_regs(BasicType type) { // Sparc requires two cpu registers for long // and two cpu registers for double -#ifdef _LP64 if (type == T_DOUBLE) { -#else - if (type == T_DOUBLE || type == T_LONG) { -#endif return 2; } return 1; @@ -44,11 +40,7 @@ inline int LinearScan::num_physical_regs(BasicType type) { inline bool LinearScan::requires_adjacent_regs(BasicType type) { -#ifdef _LP64 return type == T_DOUBLE; -#else - return type == T_DOUBLE || type == T_LONG; -#endif } inline bool LinearScan::is_caller_save(int assigned_reg) { diff --git a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp index fbd0e1ce6b4..fa0cde6e6ed 100644 --- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -273,13 +273,6 @@ void C1_MacroAssembler::initialize_object( add(obj, hdr_size_in_bytes, t1); // compute address of first element sub(var_size_in_bytes, hdr_size_in_bytes, t2); // compute size of body initialize_body(t1, t2); -#ifndef _LP64 - } else if (con_size_in_bytes < threshold * 2) { - // on v9 we can do double word stores to fill twice as much space. - assert(hdr_size_in_bytes % 8 == 0, "double word aligned"); - assert(con_size_in_bytes % 8 == 0, "double word aligned"); - for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += 2 * HeapWordSize) stx(G0, obj, i); -#endif } else if (con_size_in_bytes <= threshold) { // use explicit NULL stores for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += HeapWordSize) st_ptr(G0, obj, i); diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp index 40e30551967..baadab70bac 100644 --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @@ -35,6 +35,7 @@ #include "runtime/signature.hpp" #include "runtime/vframeArray.hpp" #include "utilities/macros.hpp" +#include "utilities/align.hpp" #include "vmreg_sparc.inline.hpp" #if INCLUDE_ALL_GCS #include "gc/g1/g1SATBCardTableModRefBS.hpp" @@ -251,7 +252,7 @@ void Runtime1::initialize_pd() { // SP -> --------------- // int i; - int sp_offset = round_to(frame::register_save_words, 2); // start doubleword aligned + int sp_offset = align_up((int)frame::register_save_words, 2); // start doubleword aligned // only G int registers are saved explicitly; others are found in register windows for (i = 0; i < FrameMap::nof_cpu_regs; i++) { @@ -272,7 +273,7 @@ void Runtime1::initialize_pd() { // this should match assembler::total_frame_size_in_bytes, which // isn't callable from this context. It's checked by an assert when // it's used though. - frame_size_in_bytes = align_size_up(sp_offset * wordSize, 8); + frame_size_in_bytes = align_up(sp_offset * wordSize, 8); } @@ -930,11 +931,7 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { Label not_already_dirty, restart, refill, young_card; -#ifdef _LP64 __ srlx(addr, CardTableModRefBS::card_shift, addr); -#else - __ srl(addr, CardTableModRefBS::card_shift, addr); -#endif AddressLiteral rs(byte_map_base); __ set(rs, cardtable); // cardtable := diff --git a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp index 7e7cddc54da..27a0009c1a8 100644 --- a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -33,7 +33,7 @@ define_pd_global(bool, BackgroundCompilation, true); define_pd_global(bool, CICompileOSR, true); -define_pd_global(bool, InlineIntrinsics, false); +define_pd_global(bool, InlineIntrinsics, true); define_pd_global(bool, PreferInterpreterNativeStubs, false); define_pd_global(bool, ProfileTraps, true); define_pd_global(bool, UseOnStackReplacement, true); @@ -65,7 +65,6 @@ define_pd_global(bool, OptoRegScheduling, false); define_pd_global(bool, SuperWordLoopUnrollAnalysis, false); define_pd_global(bool, IdealizeClearArrayNode, true); -#ifdef _LP64 // We need to make sure that all generated code is within // 2 gigs of the libjvm.so runtime routines so we can use // the faster "call" instruction rather than the expensive @@ -81,17 +80,6 @@ define_pd_global(intx, CodeCacheExpansionSize, 64*K); // Ergonomics related flags define_pd_global(uint64_t,MaxRAM, 128ULL*G); -#else -// InitialCodeCacheSize derived from specjbb2000 run. -define_pd_global(intx, InitialCodeCacheSize, 1536*K); // Integral multiple of CodeCacheExpansionSize -define_pd_global(intx, ReservedCodeCacheSize, 32*M); -define_pd_global(intx, NonProfiledCodeHeapSize, 13*M); -define_pd_global(intx, ProfiledCodeHeapSize, 14*M); -define_pd_global(intx, NonNMethodCodeHeapSize, 5*M ); -define_pd_global(intx, CodeCacheExpansionSize, 32*K); -// Ergonomics related flags -define_pd_global(uint64_t, MaxRAM, 4ULL*G); -#endif define_pd_global(uintx, CodeCacheMinBlockLength, 4); define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); diff --git a/hotspot/src/cpu/sparc/vm/copy_sparc.hpp b/hotspot/src/cpu/sparc/vm/copy_sparc.hpp index a9107d8dfdd..ae1dd0b5dcf 100644 --- a/hotspot/src/cpu/sparc/vm/copy_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/copy_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -114,14 +114,8 @@ static void pd_conjoint_jints_atomic(jint* from, jint* to, size_t count) { } static void pd_conjoint_jlongs_atomic(jlong* from, jlong* to, size_t count) { -#ifdef _LP64 assert(BytesPerLong == BytesPerOop, "jlongs and oops must be the same size"); pd_conjoint_oops_atomic((oop*)from, (oop*)to, count); -#else - // Guarantee use of ldd/std via some asm code, because compiler won't. - // See solaris_sparc.il. - _Copy_conjoint_jlongs_atomic(from, to, count); -#endif } static void pd_conjoint_oops_atomic(oop* from, oop* to, size_t count) { @@ -162,7 +156,6 @@ static void pd_arrayof_conjoint_oops(HeapWord* from, HeapWord* to, size_t count) } static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) { -#ifdef _LP64 guarantee(mask_bits((uintptr_t)tohw, right_n_bits(LogBytesPerLong)) == 0, "unaligned fill words"); julong* to = (julong*)tohw; @@ -170,12 +163,6 @@ static void pd_fill_to_words(HeapWord* tohw, size_t count, juint value) { while (count-- > 0) { *to++ = v; } -#else // _LP64 - juint* to = (juint*)tohw; - while (count-- > 0) { - *to++ = value; - } -#endif // _LP64 } typedef void (*_zero_Fn)(HeapWord* to, size_t count); diff --git a/hotspot/src/cpu/sparc/vm/debug_sparc.cpp b/hotspot/src/cpu/sparc/vm/debug_sparc.cpp deleted file mode 100644 index 9f3f40ada7c..00000000000 --- a/hotspot/src/cpu/sparc/vm/debug_sparc.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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 "code/codeCache.hpp" -#include "code/nmethod.hpp" -#include "runtime/frame.hpp" -#include "runtime/init.hpp" -#include "runtime/os.hpp" -#include "utilities/debug.hpp" - -#ifndef PRODUCT - -extern "C" void findpc(int x); - - -void pd_ps(frame f) { - intptr_t* sp = f.sp(); - intptr_t* prev_sp = sp - 1; - intptr_t *pc = NULL; - intptr_t *next_pc = NULL; - int count = 0; - tty->print_cr("register window backtrace from " INTPTR_FORMAT ":", p2i(sp)); - while (sp != NULL && ((intptr_t)sp & 7) == 0 && sp > prev_sp && sp < prev_sp+1000) { - pc = next_pc; - next_pc = (intptr_t*) sp[I7->sp_offset_in_saved_window()]; - tty->print("[%d] sp=" INTPTR_FORMAT " pc=", count, p2i(sp)); - findpc((intptr_t)pc); - if (WizardMode && Verbose) { - // print register window contents also - tty->print_cr(" L0..L7: {" - INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " - INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " ", - sp[0+0], sp[0+1], sp[0+2], sp[0+3], - sp[0+4], sp[0+5], sp[0+6], sp[0+7]); - tty->print_cr(" I0..I7: {" - INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " - INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " ", - sp[8+0], sp[8+1], sp[8+2], sp[8+3], - sp[8+4], sp[8+5], sp[8+6], sp[8+7]); - // (and print stack frame contents too??) - - CodeBlob *b = CodeCache::find_blob((address) pc); - if (b != NULL) { - if (b->is_nmethod()) { - Method* m = ((nmethod*)b)->method(); - int nlocals = m->max_locals(); - int nparams = m->size_of_parameters(); - tty->print_cr("compiled java method (locals = %d, params = %d)", nlocals, nparams); - } - } - } - prev_sp = sp; - sp = (intptr_t *)sp[FP->sp_offset_in_saved_window()]; - sp = (intptr_t *)((intptr_t)sp + STACK_BIAS); - count += 1; - } - if (sp != NULL) - tty->print("[%d] sp=" INTPTR_FORMAT " [bogus sp!]", count, p2i(sp)); -} - -#endif // PRODUCT diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp index c666f1eca47..4fa7e6a973b 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -114,11 +114,7 @@ address RegisterMap::pd_location(VMReg regname) const { // register locations. When that is fixed we'd will return NULL // (or assert here). reg = regname->prev()->as_Register(); -#ifdef _LP64 second_word = sizeof(jint); -#else - return NULL; -#endif // _LP64 } else { reg = regname->as_Register(); } @@ -332,9 +328,7 @@ bool frame::safe_for_sender(JavaThread *thread) { // Construct an unpatchable, deficient frame void frame::init(intptr_t* sp, address pc, CodeBlob* cb) { -#ifdef _LP64 assert( (((intptr_t)sp & (wordSize-1)) == 0), "frame constructor passed an invalid sp"); -#endif _sp = sp; _younger_sp = NULL; _pc = pc; @@ -410,7 +404,55 @@ frame::frame(intptr_t* sp, intptr_t* younger_sp, bool younger_frame_is_interpret frame::frame(void* sp, void* fp, void* pc) { init((intptr_t*)sp, (address)pc, NULL); } -#endif + +extern "C" void findpc(intptr_t x); + +void frame::pd_ps() { + intptr_t* curr_sp = sp(); + intptr_t* prev_sp = curr_sp - 1; + intptr_t *pc = NULL; + intptr_t *next_pc = NULL; + int count = 0; + tty->print_cr("register window backtrace from " INTPTR_FORMAT ":", p2i(curr_sp)); + while (curr_sp != NULL && ((intptr_t)curr_sp & 7) == 0 && curr_sp > prev_sp && curr_sp < prev_sp+1000) { + pc = next_pc; + next_pc = (intptr_t*) curr_sp[I7->sp_offset_in_saved_window()]; + tty->print("[%d] curr_sp=" INTPTR_FORMAT " pc=", count, p2i(curr_sp)); + findpc((intptr_t)pc); + if (WizardMode && Verbose) { + // print register window contents also + tty->print_cr(" L0..L7: {" + INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " + INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " ", + curr_sp[0+0], curr_sp[0+1], curr_sp[0+2], curr_sp[0+3], + curr_sp[0+4], curr_sp[0+5], curr_sp[0+6], curr_sp[0+7]); + tty->print_cr(" I0..I7: {" + INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " + INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " " INTPTR_FORMAT " ", + curr_sp[8+0], curr_sp[8+1], curr_sp[8+2], curr_sp[8+3], + curr_sp[8+4], curr_sp[8+5], curr_sp[8+6], curr_sp[8+7]); + // (and print stack frame contents too??) + + CodeBlob *b = CodeCache::find_blob((address) pc); + if (b != NULL) { + if (b->is_nmethod()) { + Method* m = ((nmethod*)b)->method(); + int nlocals = m->max_locals(); + int nparams = m->size_of_parameters(); + tty->print_cr("compiled java method (locals = %d, params = %d)", nlocals, nparams); + } + } + } + prev_sp = curr_sp; + curr_sp = (intptr_t *)curr_sp[FP->sp_offset_in_saved_window()]; + curr_sp = (intptr_t *)((intptr_t)curr_sp + STACK_BIAS); + count += 1; + } + if (curr_sp != NULL) + tty->print("[%d] curr_sp=" INTPTR_FORMAT " [bogus sp!]", count, p2i(curr_sp)); +} + +#endif // PRODUCT bool frame::is_interpreted_frame() const { return Interpreter::contains(pc()); @@ -693,11 +735,9 @@ BasicType frame::interpreter_frame_result(oop* oop_result, jvalue* value_result) intptr_t* d_scratch = fp() + interpreter_frame_d_scratch_fp_offset; address l_addr = (address)l_scratch; -#ifdef _LP64 // On 64-bit the result for 1/8/16/32-bit result types is in the other // word half l_addr += wordSize/2; -#endif switch (type) { case T_OBJECT: diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp index 48cf45bd714..b3f16e4e377 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -100,11 +100,7 @@ // size of each block, in order of increasing address: register_save_words = 16, -#ifdef _LP64 callee_aggregate_return_pointer_words = 0, -#else - callee_aggregate_return_pointer_words = 1, -#endif callee_register_argument_save_area_words = 6, // memory_parameter_words = , diff --git a/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp b/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp index e10261f5033..efc92775e37 100644 --- a/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp +++ b/hotspot/src/cpu/sparc/vm/frame_sparc.inline.hpp @@ -27,6 +27,7 @@ #include "asm/macroAssembler.hpp" #include "code/vmreg.inline.hpp" +#include "utilities/align.hpp" // Inline functions for SPARC frames: @@ -134,7 +135,7 @@ inline void frame::interpreter_frame_set_tos_address( intptr_t* x ) { // Also begin is one past last monitor. inline BasicObjectLock* frame::interpreter_frame_monitor_begin() const { - int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words, WordsPerLong); + int rounded_vm_local_words = align_up((int)frame::interpreter_frame_vm_local_words, WordsPerLong); return (BasicObjectLock *)fp_addr_at(-rounded_vm_local_words); } @@ -148,7 +149,7 @@ inline void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) { } inline int frame::interpreter_frame_monitor_size() { - return round_to(BasicObjectLock::size(), WordsPerLong); + return align_up(BasicObjectLock::size(), WordsPerLong); } inline Method** frame::interpreter_frame_method_addr() const { diff --git a/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp b/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp index ba6d99cd8ea..465a6a014e3 100644 --- a/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/globalDefinitions_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2017, 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 @@ -38,24 +38,14 @@ const bool CCallingConventionRequiresIntsAsLongs = true; // The expected size in bytes of a cache line, used to pad data structures. #if defined(TIERED) - #ifdef _LP64 - // tiered, 64-bit, large machine - #define DEFAULT_CACHE_LINE_SIZE 128 - #else - // tiered, 32-bit, medium machine - #define DEFAULT_CACHE_LINE_SIZE 64 - #endif + // tiered, 64-bit, large machine + #define DEFAULT_CACHE_LINE_SIZE 128 #elif defined(COMPILER1) // pure C1, 32-bit, small machine #define DEFAULT_CACHE_LINE_SIZE 16 #elif defined(COMPILER2) || defined(SHARK) - #ifdef _LP64 - // pure C2, 64-bit, large machine - #define DEFAULT_CACHE_LINE_SIZE 128 - #else - // pure C2, 32-bit, medium machine - #define DEFAULT_CACHE_LINE_SIZE 64 - #endif + // pure C2, 64-bit, large machine + #define DEFAULT_CACHE_LINE_SIZE 128 #endif #if defined(SOLARIS) diff --git a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp index ae9ba7e467f..89361fcddbd 100644 --- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -56,18 +56,10 @@ define_pd_global(intx, InlineSmallCode, 1500); #define DEFAULT_STACK_RED_PAGES (1) #define DEFAULT_STACK_RESERVED_PAGES (SOLARIS_ONLY(1) NOT_SOLARIS(0)) -#ifdef _LP64 -// Stack slots are 2X larger in LP64 than in the 32 bit VM. define_pd_global(intx, CompilerThreadStackSize, 1024); define_pd_global(intx, ThreadStackSize, 1024); define_pd_global(intx, VMThreadStackSize, 1024); #define DEFAULT_STACK_SHADOW_PAGES (20 DEBUG_ONLY(+2)) -#else -define_pd_global(intx, CompilerThreadStackSize, 512); -define_pd_global(intx, ThreadStackSize, 512); -define_pd_global(intx, VMThreadStackSize, 512); -#define DEFAULT_STACK_SHADOW_PAGES (6 DEBUG_ONLY(+2)) -#endif // _LP64 #define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES #define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES @@ -125,9 +117,6 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); "Minimum size in bytes when block copy will be used") \ range(1, max_jint) \ \ - develop(bool, UseV8InstrsOnly, false, \ - "Use SPARC-V8 Compliant instruction subset") \ - \ product(bool, UseNiagaraInstrs, false, \ "Use Niagara-efficient instruction subset") \ \ diff --git a/hotspot/src/cpu/sparc/vm/icBuffer_sparc.cpp b/hotspot/src/cpu/sparc/vm/icBuffer_sparc.cpp index d6942f6a7ca..5b384514489 100644 --- a/hotspot/src/cpu/sparc/vm/icBuffer_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/icBuffer_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -32,13 +32,9 @@ #include "oops/oop.inline.hpp" int InlineCacheBuffer::ic_stub_code_size() { -#ifdef _LP64 return (NativeMovConstReg::instruction_size + // sethi;add NativeJump::instruction_size + // sethi; jmp; delay slot (1*BytesPerInstWord) + 1); // flush + 1 extra byte -#else - return (2+2+ 1) * wordSize + 1; // set/jump_to/nop + 1 byte so that code_end can be set in CodeBuffer -#endif } void InlineCacheBuffer::assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point) { diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp index ef2362897f7..16f20fb99d1 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -38,11 +38,7 @@ #include "runtime/biasedLocking.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/thread.inline.hpp" - -#ifndef FAST_DISPATCH -#define FAST_DISPATCH 1 -#endif -#undef FAST_DISPATCH +#include "utilities/align.hpp" // Implementation of InterpreterMacroAssembler @@ -70,7 +66,7 @@ void InterpreterMacroAssembler::compute_extra_locals_size_in_bytes(Register args br(Assembler::negative, true, Assembler::pt, skip_move); delayed()->mov(G0, delta); bind(skip_move); - round_to(delta, WordsPerLong); // make multiple of 2 (SP must be 2-word aligned) + align_up(delta, WordsPerLong); // make multiple of 2 (SP must be 2-word aligned) sll(delta, LogBytesPerWord, delta); // extra space for locals in bytes } @@ -78,23 +74,12 @@ void InterpreterMacroAssembler::compute_extra_locals_size_in_bytes(Register args // own dispatch. The dispatch address is computed and placed in IdispatchAddress void InterpreterMacroAssembler::dispatch_prolog(TosState state, int bcp_incr) { assert_not_delayed(); -#ifdef FAST_DISPATCH - // FAST_DISPATCH and ProfileInterpreter are mutually exclusive since - // they both use I2. - assert(!ProfileInterpreter, "FAST_DISPATCH and +ProfileInterpreter are mutually exclusive"); - ldub(Lbcp, bcp_incr, Lbyte_code); // load next bytecode - add(Lbyte_code, Interpreter::distance_from_dispatch_table(state), Lbyte_code); - // add offset to correct dispatch table - sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize - ld_ptr(IdispatchTables, Lbyte_code, IdispatchAddress);// get entry addr -#else ldub( Lbcp, bcp_incr, Lbyte_code); // load next bytecode // dispatch table to use AddressLiteral tbl(Interpreter::dispatch_table(state)); sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize set(tbl, G3_scratch); // compute addr of table ld_ptr(G3_scratch, Lbyte_code, IdispatchAddress); // get entry addr -#endif } @@ -281,23 +266,11 @@ void InterpreterMacroAssembler::dispatch_Lbyte_code(TosState state, address* tab // %%%%% maybe implement +VerifyActivationFrameSize here //verify_thread(); //too slow; we will just verify on method entry & exit if (verify) interp_verify_oop(Otos_i, state, __FILE__, __LINE__); -#ifdef FAST_DISPATCH - if (table == Interpreter::dispatch_table(state)) { - // use IdispatchTables - add(Lbyte_code, Interpreter::distance_from_dispatch_table(state), Lbyte_code); - // add offset to correct dispatch table - sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize - ld_ptr(IdispatchTables, Lbyte_code, G3_scratch); // get entry addr - } else { -#endif - // dispatch table to use - AddressLiteral tbl(table); - sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize - set(tbl, G3_scratch); // compute addr of table - ld_ptr(G3_scratch, Lbyte_code, G3_scratch); // get entry addr -#ifdef FAST_DISPATCH - } -#endif + // dispatch table to use + AddressLiteral tbl(table); + sll(Lbyte_code, LogBytesPerWord, Lbyte_code); // multiply by wordSize + set(tbl, G3_scratch); // compute addr of table + ld_ptr(G3_scratch, Lbyte_code, G3_scratch); // get entry addr jmp( G3_scratch, 0 ); if (bcp_incr != 0) delayed()->inc(Lbcp, bcp_incr); else delayed()->nop(); @@ -318,52 +291,32 @@ void InterpreterMacroAssembler::dispatch_Lbyte_code(TosState state, address* tab void InterpreterMacroAssembler::load_unaligned_double(Register r1, int offset, FloatRegister d) { assert_not_delayed(); -#ifdef _LP64 ldf(FloatRegisterImpl::D, r1, offset, d); -#else - ldf(FloatRegisterImpl::S, r1, offset, d); - ldf(FloatRegisterImpl::S, r1, offset + Interpreter::stackElementSize, d->successor()); -#endif } // Known good alignment in _LP64 but unknown otherwise void InterpreterMacroAssembler::store_unaligned_double(FloatRegister d, Register r1, int offset) { assert_not_delayed(); -#ifdef _LP64 stf(FloatRegisterImpl::D, d, r1, offset); // store something more useful here debug_only(stx(G0, r1, offset+Interpreter::stackElementSize);) -#else - stf(FloatRegisterImpl::S, d, r1, offset); - stf(FloatRegisterImpl::S, d->successor(), r1, offset + Interpreter::stackElementSize); -#endif } // Known good alignment in _LP64 but unknown otherwise void InterpreterMacroAssembler::load_unaligned_long(Register r1, int offset, Register rd) { assert_not_delayed(); -#ifdef _LP64 ldx(r1, offset, rd); -#else - ld(r1, offset, rd); - ld(r1, offset + Interpreter::stackElementSize, rd->successor()); -#endif } // Known good alignment in _LP64 but unknown otherwise void InterpreterMacroAssembler::store_unaligned_long(Register l, Register r1, int offset) { assert_not_delayed(); -#ifdef _LP64 stx(l, r1, offset); // store something more useful here stx(G0, r1, offset+Interpreter::stackElementSize); -#else - st(l, r1, offset); - st(l->successor(), r1, offset + Interpreter::stackElementSize); -#endif } void InterpreterMacroAssembler::pop_i(Register r) { @@ -527,9 +480,7 @@ void InterpreterMacroAssembler::empty_expression_stack() { sub( Lesp, Gframe_size, Gframe_size ); and3( Gframe_size, -(2 * wordSize), Gframe_size ); // align SP (downwards) to an 8/16-byte boundary debug_only(verify_sp(Gframe_size, G4_scratch)); -#ifdef _LP64 sub(Gframe_size, STACK_BIAS, Gframe_size ); -#endif mov(Gframe_size, SP); bind(done); @@ -541,28 +492,20 @@ void InterpreterMacroAssembler::verify_sp(Register Rsp, Register Rtemp) { Label Bad, OK; // Saved SP must be aligned. -#ifdef _LP64 btst(2*BytesPerWord-1, Rsp); -#else - btst(LongAlignmentMask, Rsp); -#endif br(Assembler::notZero, false, Assembler::pn, Bad); delayed()->nop(); // Saved SP, plus register window size, must not be above FP. add(Rsp, frame::register_save_words * wordSize, Rtemp); -#ifdef _LP64 sub(Rtemp, STACK_BIAS, Rtemp); // Bias Rtemp before cmp to FP -#endif cmp_and_brx_short(Rtemp, FP, Assembler::greaterUnsigned, Assembler::pn, Bad); // Saved SP must not be ridiculously below current SP. size_t maxstack = MAX2(JavaThread::stack_size_at_create(), (size_t) 4*K*K); set(maxstack, Rtemp); sub(SP, Rtemp, Rtemp); -#ifdef _LP64 add(Rtemp, STACK_BIAS, Rtemp); // Unbias Rtemp before cmp to Rsp -#endif cmp_and_brx_short(Rsp, Rtemp, Assembler::lessUnsigned, Assembler::pn, Bad); ba_short(OK); @@ -584,9 +527,7 @@ void InterpreterMacroAssembler::verify_esp(Register Resp) { delayed()->sub(Resp, frame::memory_parameter_word_sp_offset * wordSize, Resp); stop("too many pops: Lesp points into monitor area"); bind(OK1); -#ifdef _LP64 sub(Resp, STACK_BIAS, Resp); -#endif cmp(Resp, SP); brx(Assembler::greaterEqualUnsigned, false, Assembler::pt, OK2); delayed()->add(Resp, STACK_BIAS + frame::memory_parameter_word_sp_offset * wordSize, Resp); @@ -696,21 +637,12 @@ void InterpreterMacroAssembler::get_4_byte_integer_at_bcp( } br(Assembler::zero, true, Assembler::pn, aligned); -#ifdef _LP64 delayed()->ldsw(Rtmp, 0, Rdst); -#else - delayed()->ld(Rtmp, 0, Rdst); -#endif ldub(Lbcp, bcp_offset + 3, Rdst); ldub(Lbcp, bcp_offset + 2, Rtmp); sll(Rtmp, 8, Rtmp); or3(Rtmp, Rdst, Rdst); ldub(Lbcp, bcp_offset + 1, Rtmp); sll(Rtmp, 16, Rtmp); or3(Rtmp, Rdst, Rdst); -#ifdef _LP64 ldsb(Lbcp, bcp_offset + 0, Rtmp); sll(Rtmp, 24, Rtmp); -#else - // Unsigned load is faster than signed on some implementations - ldub(Lbcp, bcp_offset + 0, Rtmp); sll(Rtmp, 24, Rtmp); -#endif or3(Rtmp, Rdst, Rdst ); bind(aligned); @@ -796,7 +728,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( sll(index, LogBytesPerHeapOop, tmp); get_constant_pool(result); // load pointer for resolved_references[] objArray - ld_ptr(result, ConstantPool::resolved_references_offset_in_bytes(), result); + ld_ptr(result, ConstantPool::cache_offset_in_bytes(), result); + ld_ptr(result, ConstantPoolCache::resolved_references_offset_in_bytes(), result); // JNIHandles::resolve(result) ld_ptr(result, 0, result); // Add in the index @@ -805,6 +738,24 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( } +// load cpool->resolved_klass_at(index) +void InterpreterMacroAssembler::load_resolved_klass_at_offset(Register Rcpool, + Register Roffset, Register Rklass) { + // int value = *this_cp->int_at_addr(which); + // int resolved_klass_index = extract_low_short_from_int(value); + // + // Because SPARC is big-endian, the low_short is at (cpool->int_at_addr(which) + 2 bytes) + add(Roffset, Rcpool, Roffset); + lduh(Roffset, sizeof(ConstantPool) + 2, Roffset); // Roffset = resolved_klass_index + + Register Rresolved_klasses = Rklass; + ld_ptr(Rcpool, ConstantPool::resolved_klasses_offset_in_bytes(), Rresolved_klasses); + sll(Roffset, LogBytesPerWord, Roffset); + add(Roffset, Array::base_offset_in_bytes(), Roffset); + ld_ptr(Rresolved_klasses, Roffset, Rklass); +} + + // Generate a subtype check: branch to ok_is_subtype if sub_klass is // a subtype of super_klass. Blows registers Rsuper_klass, Rsub_klass, tmp1, tmp2. void InterpreterMacroAssembler::gen_subtype_check(Register Rsub_klass, @@ -910,10 +861,8 @@ void InterpreterMacroAssembler::index_check_without_pop(Register array, Register assert_not_delayed(); verify_oop(array); -#ifdef _LP64 // sign extend since tos (index) can be a 32bit value sra(index, G0, index); -#endif // _LP64 // check array Label ptr_ok; @@ -1191,11 +1140,7 @@ void InterpreterMacroAssembler::remove_activation(TosState state, // return tos assert(Otos_l1 == Otos_i, "adjust code below"); switch (state) { -#ifdef _LP64 case ltos: mov(Otos_l, Otos_l->after_save()); break; // O0 -> I0 -#else - case ltos: mov(Otos_l2, Otos_l2->after_save()); // fall through // O1 -> I1 -#endif case btos: // fall through case ztos: // fall through case ctos: @@ -1207,20 +1152,6 @@ void InterpreterMacroAssembler::remove_activation(TosState state, case vtos: /* nothing to do */ break; default : ShouldNotReachHere(); } - -#if defined(COMPILER2) && !defined(_LP64) - if (state == ltos) { - // C2 expects long results in G1 we can't tell if we're returning to interpreted - // or compiled so just be safe use G1 and O0/O1 - - // Shift bits into high (msb) of G1 - sllx(Otos_l1->after_save(), 32, G1); - // Zero extend low bits - srl (Otos_l2->after_save(), 0, Otos_l2->after_save()); - or3 (Otos_l2->after_save(), G1, G1); - } -#endif /* COMPILER2 */ - } // Lock object @@ -1270,9 +1201,7 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg, Register Object) // Check if owner is self by comparing the value in the markOop of object // with the stack pointer sub(temp_reg, SP, temp_reg); -#ifdef _LP64 sub(temp_reg, STACK_BIAS, temp_reg); -#endif assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); // Composite "andcc" test: @@ -2381,7 +2310,7 @@ void InterpreterMacroAssembler::store_local_double( Register index, FloatRegiste int InterpreterMacroAssembler::top_most_monitor_byte_offset() { const jint delta = frame::interpreter_frame_monitor_size() * wordSize; - int rounded_vm_local_words = ::round_to(frame::interpreter_frame_vm_local_words, WordsPerLong); + int rounded_vm_local_words = align_up((int)frame::interpreter_frame_vm_local_words, WordsPerLong); return ((-rounded_vm_local_words * wordSize) - delta ) + STACK_BIAS; } @@ -2711,11 +2640,7 @@ void InterpreterMacroAssembler::notify_method_exit(bool is_native_method, void InterpreterMacroAssembler::save_return_value(TosState state, bool is_native_call) { if (is_native_call) { stf(FloatRegisterImpl::D, F0, d_tmp); -#ifdef _LP64 stx(O0, l_tmp); -#else - std(O0, l_tmp); -#endif } else { push(state); } @@ -2724,11 +2649,7 @@ void InterpreterMacroAssembler::save_return_value(TosState state, bool is_native void InterpreterMacroAssembler::restore_return_value( TosState state, bool is_native_call) { if (is_native_call) { ldf(FloatRegisterImpl::D, d_tmp, F0); -#ifdef _LP64 ldx(l_tmp, O0); -#else - ldd(l_tmp, O0); -#endif } else { pop(state); } diff --git a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp index 1baceb1233c..23e85374904 100644 --- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -70,9 +70,6 @@ class InterpreterMacroAssembler: public MacroAssembler { bool check_exception=true ); - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - // base routine for all dispatches void dispatch_base(TosState state, address* table); @@ -80,6 +77,9 @@ class InterpreterMacroAssembler: public MacroAssembler { InterpreterMacroAssembler(CodeBuffer* c) : MacroAssembler(c) {} + virtual void check_and_handle_popframe(Register scratch_reg); + virtual void check_and_handle_earlyret(Register scratch_reg); + void jump_to_entry(address entry); virtual void load_earlyret_value(TosState state); @@ -196,6 +196,9 @@ class InterpreterMacroAssembler: public MacroAssembler { // load cpool->resolved_references(index); void load_resolved_reference_at_index(Register result, Register index); + // load cpool->resolved_klass_at(index) + void load_resolved_klass_at_offset(Register Rcpool, Register Roffset, Register Rklass); + // common code void field_offset_at(int n, Register tmp, Register dest, Register base); diff --git a/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp b/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp index 0e1d6c992cd..0bd430b2217 100644 --- a/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -53,47 +53,24 @@ void InterpreterRuntime::SignatureHandlerGenerator::pass_long() { Argument jni_arg(jni_offset(), false); Register Rtmp = O0; -#ifdef _LP64 __ ldx(Llocals, Interpreter::local_offset_in_bytes(offset() + 1), Rtmp); __ store_long_argument(Rtmp, jni_arg); -#else - __ ld(Llocals, Interpreter::local_offset_in_bytes(offset() + 1), Rtmp); - __ store_argument(Rtmp, jni_arg); - __ ld(Llocals, Interpreter::local_offset_in_bytes(offset() + 0), Rtmp); - Argument successor(jni_arg.successor()); - __ store_argument(Rtmp, successor); -#endif } void InterpreterRuntime::SignatureHandlerGenerator::pass_float() { Argument jni_arg(jni_offset(), false); -#ifdef _LP64 FloatRegister Rtmp = F0; __ ldf(FloatRegisterImpl::S, Llocals, Interpreter::local_offset_in_bytes(offset()), Rtmp); __ store_float_argument(Rtmp, jni_arg); -#else - Register Rtmp = O0; - __ ld(Llocals, Interpreter::local_offset_in_bytes(offset()), Rtmp); - __ store_argument(Rtmp, jni_arg); -#endif } void InterpreterRuntime::SignatureHandlerGenerator::pass_double() { Argument jni_arg(jni_offset(), false); -#ifdef _LP64 FloatRegister Rtmp = F0; __ ldf(FloatRegisterImpl::D, Llocals, Interpreter::local_offset_in_bytes(offset() + 1), Rtmp); __ store_double_argument(Rtmp, jni_arg); -#else - Register Rtmp = O0; - __ ld(Llocals, Interpreter::local_offset_in_bytes(offset() + 1), Rtmp); - __ store_argument(Rtmp, jni_arg); - __ ld(Llocals, Interpreter::local_offset_in_bytes(offset()), Rtmp); - Argument successor(jni_arg.successor()); - __ store_argument(Rtmp, successor); -#endif } void InterpreterRuntime::SignatureHandlerGenerator::pass_object() { @@ -171,7 +148,6 @@ class SlowSignatureHandler: public NativeSignatureIterator { add_signature( non_float ); } -#ifdef _LP64 virtual void pass_float() { *_to++ = *(jint *)(_from+Interpreter::local_offset_in_bytes(0)); _from -= Interpreter::stackElementSize; @@ -190,23 +166,6 @@ class SlowSignatureHandler: public NativeSignatureIterator { _from -= 2*Interpreter::stackElementSize; add_signature( long_sig ); } -#else - // pass_double() is pass_long() and pass_float() only _LP64 - virtual void pass_long() { - _to[0] = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(1)); - _to[1] = *(intptr_t*)(_from+Interpreter::local_offset_in_bytes(0)); - _to += 2; - _from -= 2*Interpreter::stackElementSize; - add_signature( non_float ); - } - - virtual void pass_float() { - *_to++ = *(jint *)(_from+Interpreter::local_offset_in_bytes(0)); - _from -= Interpreter::stackElementSize; - add_signature( non_float ); - } - -#endif // _LP64 virtual void add_signature( intptr_t sig_type ) { if ( _argcount < (sizeof (intptr_t))*4 ) { @@ -217,7 +176,7 @@ class SlowSignatureHandler: public NativeSignatureIterator { public: - SlowSignatureHandler(methodHandle method, address from, intptr_t* to, intptr_t *RegArgSig) : NativeSignatureIterator(method) { + SlowSignatureHandler(const methodHandle& method, address from, intptr_t* to, intptr_t *RegArgSig) : NativeSignatureIterator(method) { _from = from; _to = to; _RegArgSignature = RegArgSig; diff --git a/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.hpp b/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.hpp index 6d90042c013..72ca060f979 100644 --- a/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/interpreterRT_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -52,7 +52,7 @@ class SignatureHandlerGenerator: public NativeSignatureIterator { public: // Creation - SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) { + SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) { _masm = new MacroAssembler(buffer); } diff --git a/hotspot/src/cpu/sparc/vm/javaFrameAnchor_sparc.hpp b/hotspot/src/cpu/sparc/vm/javaFrameAnchor_sparc.hpp index 1b4b3bf2ffc..c51545c09cc 100644 --- a/hotspot/src/cpu/sparc/vm/javaFrameAnchor_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/javaFrameAnchor_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -88,9 +88,7 @@ private: // _last_Java_sp will always be a an unbiased stack pointer // if is is biased then some setter screwed up. This is // deadly. -#ifdef _LP64 assert(((intptr_t)_last_Java_sp & 0xF) == 0, "Biased last_Java_sp"); -#endif return _last_Java_sp; } diff --git a/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp b/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp index ff9fcd69472..178b9c74870 100644 --- a/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/jniFastGetField_sparc.cpp @@ -152,39 +152,19 @@ address JNI_FastGetField::generate_fast_get_long_field() { __ ld_ptr (O1, 0, O5); __ add (O5, O4, O5); -#ifndef _LP64 - assert(count < LIST_CAPACITY-1, "LIST_CAPACITY too small"); - speculative_load_pclist[count++] = __ pc(); - __ ld (O5, 0, G2); - - speculative_load_pclist[count] = __ pc(); - __ ld (O5, 4, O3); -#else assert(count < LIST_CAPACITY, "LIST_CAPACITY too small"); speculative_load_pclist[count] = __ pc(); __ ldx (O5, 0, O3); -#endif __ ld (cnt_addr, G1); __ cmp (G1, G4); __ br (Assembler::notEqual, false, Assembler::pn, label2); __ delayed()->mov (O7, G1); -#ifndef _LP64 - __ mov (G2, O0); - __ retl (); - __ delayed()->mov (O3, O1); -#else __ retl (); __ delayed()->mov (O3, O0); -#endif -#ifndef _LP64 - slowcase_entry_pclist[count-1] = __ pc(); - slowcase_entry_pclist[count++] = __ pc() ; -#else slowcase_entry_pclist[count++] = __ pc(); -#endif __ bind (label1); __ mov (O7, G1); diff --git a/hotspot/src/cpu/sparc/vm/jniTypes_sparc.hpp b/hotspot/src/cpu/sparc/vm/jniTypes_sparc.hpp index 9c3049141fd..50b51fff2c3 100644 --- a/hotspot/src/cpu/sparc/vm/jniTypes_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/jniTypes_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -55,18 +55,10 @@ public: static inline void put_int(jint from, intptr_t *to, int& pos) { *(jint *)(to + pos++) = from; } static inline void put_int(jint *from, intptr_t *to, int& pos) { *(jint *)(to + pos++) = *from; } -#ifdef _LP64 // Longs are stored in native format in one JavaCallArgument slot at *(to+1). static inline void put_long(jlong from, intptr_t *to) { *(jlong *)(to + 1 + 0) = from; } static inline void put_long(jlong from, intptr_t *to, int& pos) { *(jlong *)(to + 1 + pos) = from; pos += 2; } static inline void put_long(jlong *from, intptr_t *to, int& pos) { *(jlong *)(to + 1 + pos) = *from; pos += 2; } -#else - // Longs are stored in reversed native word format in two JavaCallArgument slots at *to. - // The high half is in *(to+1) and the low half in *to. - static inline void put_long(jlong from, intptr_t *to) { put_int2r((jint *)&from, (jint *)to); } - static inline void put_long(jlong from, intptr_t *to, int& pos) { put_int2r((jint *)&from, (jint *)to, pos); } - static inline void put_long(jlong *from, intptr_t *to, int& pos) { put_int2r((jint *) from, (jint *)to, pos); } -#endif // Oops are stored in native format in one JavaCallArgument slot at *to. static inline void put_obj(oop from, intptr_t *to) { *(oop *)(to + 0 ) = from; } @@ -78,39 +70,21 @@ public: static inline void put_float(jfloat from, intptr_t *to, int& pos) { *(jfloat *)(to + pos++) = from; } static inline void put_float(jfloat *from, intptr_t *to, int& pos) { *(jfloat *)(to + pos++) = *from; } -#ifdef _LP64 // Doubles are stored in native word format in one JavaCallArgument slot at *(to+1). static inline void put_double(jdouble from, intptr_t *to) { *(jdouble *)(to + 1 + 0) = from; } static inline void put_double(jdouble from, intptr_t *to, int& pos) { *(jdouble *)(to + 1 + pos) = from; pos += 2; } static inline void put_double(jdouble *from, intptr_t *to, int& pos) { *(jdouble *)(to + 1 + pos) = *from; pos += 2; } -#else - // Doubles are stored in reversed native word format in two JavaCallArgument slots at *to. - static inline void put_double(jdouble from, intptr_t *to) { put_int2r((jint *)&from, (jint *)to); } - static inline void put_double(jdouble from, intptr_t *to, int& pos) { put_int2r((jint *)&from, (jint *)to, pos); } - static inline void put_double(jdouble *from, intptr_t *to, int& pos) { put_int2r((jint *) from, (jint *)to, pos); } -#endif // The get_xxx routines, on the other hand, actually _do_ fetch // java primitive types from the interpreter stack. static inline jint get_int(intptr_t *from) { return *(jint *)from; } -#ifdef _LP64 static inline jlong get_long(intptr_t *from) { return *(jlong *)from; } -#else - static inline jlong get_long(intptr_t *from) { return ((jlong)(*( signed int *)((jint *)from )) << 32) | - ((jlong)(*(unsigned int *)((jint *)from + 1)) << 0); } -#endif static inline oop get_obj(intptr_t *from) { return *(oop *)from; } static inline jfloat get_float(intptr_t *from) { return *(jfloat *)from; } -#ifdef _LP64 static inline jdouble get_double(intptr_t *from) { return *(jdouble *)from; } -#else - static inline jdouble get_double(intptr_t *from) { jlong jl = ((jlong)(*( signed int *)((jint *)from )) << 32) | - ((jlong)(*(unsigned int *)((jint *)from + 1)) << 0); - return *(jdouble *)&jl; } -#endif }; diff --git a/hotspot/src/cpu/sparc/vm/jni_sparc.h b/hotspot/src/cpu/sparc/vm/jni_sparc.h index a7540600488..3402f67c992 100644 --- a/hotspot/src/cpu/sparc/vm/jni_sparc.h +++ b/hotspot/src/cpu/sparc/vm/jni_sparc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -39,10 +39,6 @@ typedef int jint; -#ifdef _LP64 - typedef long jlong; -#else - typedef long long jlong; -#endif +typedef long jlong; typedef signed char jbyte; diff --git a/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp b/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp index 4976e1686b2..6c3c5568d48 100644 --- a/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/jvmciCodeInstaller_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "jvmci/jvmciJavaClasses.hpp" #include "oops/oop.inline.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/align.hpp" #include "vmreg_sparc.inline.hpp" jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Handle method, TRAPS) { @@ -44,16 +45,12 @@ jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Hand void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) { address pc = _instructions->start() + pc_offset; - Handle obj = HotSpotObjectConstantImpl::object(constant); + Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant)); jobject value = JNIHandles::make_local(obj()); if (HotSpotObjectConstantImpl::compressed(constant)) { -#ifdef _LP64 int oop_index = _oop_recorder->find_index(value); RelocationHolder rspec = oop_Relocation::spec(oop_index); _instructions->relocate(pc, rspec, 1); -#else - JVMCI_ERROR("compressed oop on 32bit"); -#endif } else { NativeMovConstReg* move = nativeMovConstReg_at(pc); move->set_data((intptr_t) value); @@ -69,14 +66,10 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, TRAPS) { address pc = _instructions->start() + pc_offset; if (HotSpotMetaspaceConstantImpl::compressed(constant)) { -#ifdef _LP64 NativeMovConstReg32* move = nativeMovConstReg32_at(pc); narrowKlass narrowOop = record_narrow_metadata_reference(_instructions, pc, constant, CHECK); move->set_data((intptr_t)narrowOop); TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/0x%x", p2i(pc), narrowOop); -#else - JVMCI_ERROR("compressed Klass* on 32bit"); -#endif } else { NativeMovConstReg* move = nativeMovConstReg_at(pc); void* reference = record_metadata_reference(_instructions, pc, constant, CHECK); @@ -98,7 +91,7 @@ void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset } TRACE_jvmci_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset); }else { - int const_size = align_size_up(_constants->end()-_constants->start(), CodeEntryAlignment); + int const_size = align_up(_constants->end()-_constants->start(), CodeEntryAlignment); NativeMovRegMem* load = nativeMovRegMem_at(pc); // This offset must match with SPARCLoadConstantTableBaseOp.emitCode load->set_offset(- (const_size - data_offset + Assembler::min_simm13())); diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp index e0065402b05..51d01936d9b 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/klass.inline.hpp" +#include "prims/jvm.h" #include "prims/methodHandles.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/interfaceSupport.hpp" @@ -38,6 +39,7 @@ #include "runtime/os.inline.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" +#include "utilities/align.hpp" #include "utilities/macros.hpp" #if INCLUDE_ALL_GCS #include "gc/g1/g1CollectedHeap.inline.hpp" @@ -296,11 +298,6 @@ void MacroAssembler::verify_thread() { mov(G3, L3); // avoid clobbering G3 mov(G4, L4); // avoid clobbering G4 mov(G5_method, L5); // avoid clobbering G5_method -#if defined(COMPILER2) && !defined(_LP64) - // Save & restore possible 64-bit Long arguments in G-regs - srlx(G1,32,L0); - srlx(G4,32,L6); -#endif call(CAST_FROM_FN_PTR(address,verify_thread_subroutine), relocInfo::runtime_call_type); delayed()->mov(G2_thread, O0); @@ -309,15 +306,6 @@ void MacroAssembler::verify_thread() { mov(L3, G3); // restore G3 mov(L4, G4); // restore G4 mov(L5, G5_method); // restore G5_method -#if defined(COMPILER2) && !defined(_LP64) - // Save & restore possible 64-bit Long arguments in G-regs - sllx(L0,32,G2); // Move old high G1 bits high in G2 - srl(G1, 0,G1); // Clear current high G1 bits - or3 (G1,G2,G1); // Recover 64-bit G1 - sllx(L6,32,G2); // Move old high G4 bits high in G2 - srl(G4, 0,G4); // Clear current high G4 bits - or3 (G4,G2,G4); // Recover 64-bit G4 -#endif restore(O0, 0, G2_thread); } } @@ -387,7 +375,6 @@ void MacroAssembler::set_last_Java_frame(Register last_java_sp, Register last_Ja st_ptr(last_Java_pc, pc_addr); } -#ifdef _LP64 #ifdef ASSERT // Make sure that we have an odd stack Label StackOk; @@ -400,9 +387,6 @@ void MacroAssembler::set_last_Java_frame(Register last_java_sp, Register last_Ja assert( last_java_sp != G4_scratch, "bad register usage in set_last_Java_frame"); add( last_java_sp, STACK_BIAS, G4_scratch ); st_ptr(G4_scratch, G2_thread, JavaThread::last_Java_sp_offset()); -#else - st_ptr(last_java_sp, G2_thread, JavaThread::last_Java_sp_offset()); -#endif // _LP64 } void MacroAssembler::reset_last_Java_frame(void) { @@ -658,11 +642,7 @@ void MacroAssembler::ic_call(address entry, bool emit_delay, jint method_index) void MacroAssembler::card_table_write(jbyte* byte_map_base, Register tmp, Register obj) { -#ifdef _LP64 srlx(obj, CardTableModRefBS::card_shift, obj); -#else - srl(obj, CardTableModRefBS::card_shift, obj); -#endif assert(tmp != obj, "need separate temp reg"); set((address) byte_map_base, tmp); stb(G0, tmp, obj); @@ -672,10 +652,9 @@ void MacroAssembler::card_table_write(jbyte* byte_map_base, void MacroAssembler::internal_sethi(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) { address save_pc; int shiftcnt; -#ifdef _LP64 -# ifdef CHECK_DELAY - assert_not_delayed((char*) "cannot put two instructions in delay slot"); -# endif +#ifdef VALIDATE_PIPELINE + assert_no_delay("Cannot put two instructions in delay-slot."); +#endif v9_dep(); save_pc = pc(); @@ -719,9 +698,6 @@ void MacroAssembler::internal_sethi(const AddressLiteral& addrlit, Register d, b while (pc() < (save_pc + (7 * BytesPerInstWord))) nop(); } -#else - Assembler::sethi(addrlit.value(), d, addrlit.rspec()); -#endif } @@ -736,7 +712,6 @@ void MacroAssembler::patchable_sethi(const AddressLiteral& addrlit, Register d) int MacroAssembler::insts_for_sethi(address a, bool worst_case) { -#ifdef _LP64 if (worst_case) return 7; intptr_t iaddr = (intptr_t) a; int msb32 = (int) (iaddr >> 32); @@ -756,9 +731,6 @@ int MacroAssembler::insts_for_sethi(address a, bool worst_case) { } } return count; -#else - return 1; -#endif } int MacroAssembler::worst_case_insts_for_set() { @@ -781,7 +753,7 @@ void MacroAssembler::internal_set(const AddressLiteral& addrlit, Register d, boo return; } } - assert_not_delayed((char*) "cannot put two instructions in delay slot"); + assert_no_delay("Cannot put two instructions in delay-slot."); internal_sethi(addrlit, d, ForceRelocatable); if (ForceRelocatable || addrlit.rspec().type() != relocInfo::none || addrlit.low10() != 0) { add(d, addrlit.low10(), d, addrlit.rspec()); @@ -1117,7 +1089,7 @@ void RegistersForDebugging::print(outputStream* s) { } void RegistersForDebugging::save_registers(MacroAssembler* a) { - a->sub(FP, round_to(sizeof(RegistersForDebugging), sizeof(jdouble)) - STACK_BIAS, O0); + a->sub(FP, align_up(sizeof(RegistersForDebugging), sizeof(jdouble)) - STACK_BIAS, O0); a->flushw(); int i; for (i = 0; i < 8; ++i) { @@ -1339,7 +1311,7 @@ void MacroAssembler::verify_oop_subroutine() { wrccr( O5_save_flags ); // Restore CCR's - save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); + save_frame(align_up(sizeof(RegistersForDebugging) / BytesPerWord, 2)); // stop_subroutine expects message pointer in I1. mov(I1, O1); @@ -1368,7 +1340,7 @@ void MacroAssembler::stop(const char* msg) { // add one word to size in case struct is odd number of words long // It must be doubleword-aligned for storing doubles into it. - save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); + save_frame(align_up(sizeof(RegistersForDebugging) / BytesPerWord, 2)); // stop_subroutine expects message pointer in I1. // Size of set() should stay the same @@ -1391,7 +1363,7 @@ void MacroAssembler::stop(const char* msg) { void MacroAssembler::warn(const char* msg) { - save_frame(::round_to(sizeof(RegistersForDebugging) / BytesPerWord, 2)); + save_frame(align_up(sizeof(RegistersForDebugging) / BytesPerWord, 2)); RegistersForDebugging::save_registers(this); mov(O0, L0); // Size of set() should stay the same @@ -1422,6 +1394,13 @@ void MacroAssembler::untested(const char* what) { } +void MacroAssembler::unimplemented(const char* what) { + char* b = new char[1024]; + jio_snprintf(b, 1024, "unimplemented: %s", what); + stop(b); +} + + void MacroAssembler::stop_subroutine() { RegistersForDebugging::save_registers(this); @@ -1488,11 +1467,7 @@ void MacroAssembler::calc_mem_param_words(Register Rparam_words, Register Rresul void MacroAssembler::calc_frame_size(Register Rextra_words, Register Rresult) { -#ifdef _LP64 add(Rextra_words, frame::memory_parameter_word_sp_offset, Rresult); -#else - add(Rextra_words, frame::memory_parameter_word_sp_offset + 1, Rresult); -#endif bclr(1, Rresult); sll(Rresult, LogBytesPerWord, Rresult); // Rresult has total frame bytes } @@ -1531,22 +1506,12 @@ void MacroAssembler::cmp_zero_and_br(Condition c, Register s1, Label& L, bool a, // Does a test & branch on 32-bit systems and a register-branch on 64-bit. void MacroAssembler::br_null( Register s1, bool a, Predict p, Label& L ) { assert_not_delayed(); -#ifdef _LP64 bpr( rc_z, a, p, s1, L ); -#else - tst(s1); - br ( zero, a, p, L ); -#endif } void MacroAssembler::br_notnull( Register s1, bool a, Predict p, Label& L ) { assert_not_delayed(); -#ifdef _LP64 bpr( rc_nz, a, p, s1, L ); -#else - tst(s1); - br ( notZero, a, p, L ); -#endif } // Compare registers and branch with nop in delay slot or cbcond without delay slot. @@ -1862,14 +1827,12 @@ void MacroAssembler::lushr( Register Rin_high, Register Rin_low, bind( done ); } -#ifdef _LP64 void MacroAssembler::lcmp( Register Ra, Register Rb, Register Rresult) { cmp(Ra, Rb); mov(-1, Rresult); movcc(equal, false, xcc, 0, Rresult); movcc(greater, false, xcc, 1, Rresult); } -#endif void MacroAssembler::load_sized_value(Address src, Register dst, size_t size_in_bytes, bool is_signed) { @@ -2668,9 +2631,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, // if compare/exchange succeeded we found an unlocked object and we now have locked it // hence we are done cmp(Rmark, Rscratch); -#ifdef _LP64 sub(Rscratch, STACK_BIAS, Rscratch); -#endif brx(Assembler::equal, false, Assembler::pt, done); delayed()->sub(Rscratch, SP, Rscratch); //pull next instruction into delay slot @@ -2716,9 +2677,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, // Stack-lock attempt failed - check for recursive stack-lock. // See the comments below about how we might remove this case. -#ifdef _LP64 sub(Rscratch, STACK_BIAS, Rscratch); -#endif assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); andcc(Rscratch, 0xfffff003, Rscratch); br(Assembler::always, false, Assembler::pt, done); @@ -2800,9 +2759,7 @@ void MacroAssembler::compiler_lock_object(Register Roop, Register Rmark, // control to the "slow" operators in synchronizer.cpp. // RScratch contains the fetched obj->mark value from the failed CAS. -#ifdef _LP64 sub(Rscratch, STACK_BIAS, Rscratch); -#endif sub(Rscratch, SP, Rscratch); assert(os::vm_page_size() > 0xfff, "page size too small - change the constant"); andcc(Rscratch, 0xfffff003, Rscratch); @@ -3720,11 +3677,7 @@ static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) { Label not_already_dirty, restart, refill, young_card; -#ifdef _LP64 __ srlx(O0, CardTableModRefBS::card_shift, O0); -#else - __ srl(O0, CardTableModRefBS::card_shift, O0); -#endif AddressLiteral addrlit(byte_map_base); __ set(addrlit, O1); // O1 := __ ldub(O0, O1, O2); // O2 := [O0 + O1] @@ -3826,11 +3779,7 @@ void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val if (G1RSBarrierRegionFilter) { xor3(store_addr, new_val, tmp); -#ifdef _LP64 srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp); -#else - srl(tmp, HeapRegion::LogOfHRGrainBytes, tmp); -#endif // XXX Should I predict this taken or not? Does it matter? cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered); @@ -4665,7 +4614,7 @@ void MacroAssembler::has_negatives(Register inp, Register size, Register result, // Use BIS for zeroing (count is in bytes). void MacroAssembler::bis_zeroing(Register to, Register count, Register temp, Label& Ldone) { - assert(UseBlockZeroing && VM_Version::has_block_zeroing(), "only works with BIS zeroing"); + assert(UseBlockZeroing && VM_Version::has_blk_zeroing(), "only works with BIS zeroing"); Register end = count; int cache_line_size = VM_Version::prefetch_data_size(); assert(cache_line_size > 0, "cache line size should be known for this code"); diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp index a401859e774..1bcbc739c3d 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -156,7 +156,6 @@ REGISTER_DECLARATION(Register, O5_savedSP , O5); REGISTER_DECLARATION(Register, I5_savedSP , I5); // Saved SP before bumping for locals. This is simply // a copy SP, so in 64-bit it's a biased value. The bias // is added and removed as needed in the frame code. -REGISTER_DECLARATION(Register, IdispatchTables , I4); // Base address of the bytecode dispatch tables REGISTER_DECLARATION(Register, IdispatchAddress , I3); // Register which saves the dispatch address for each bytecode REGISTER_DECLARATION(Register, ImethodDataPtr , I2); // Pointer to the current method data @@ -228,7 +227,6 @@ REGISTER_DECLARATION(Register, Oissuing_pc , O1); // where the exception is comi #define O5_savedSP AS_REGISTER(Register, O5_savedSP) #define IdispatchAddress AS_REGISTER(Register, IdispatchAddress) #define ImethodDataPtr AS_REGISTER(Register, ImethodDataPtr) -#define IdispatchTables AS_REGISTER(Register, IdispatchTables) #define Oexception AS_REGISTER(Register, Oexception) #define Oissuing_pc AS_REGISTER(Register, Oissuing_pc) @@ -333,14 +331,12 @@ class AddressLiteral VALUE_OBJ_CLASS_SPEC { return external_word_Relocation::spec(addr); case relocInfo::internal_word_type: return internal_word_Relocation::spec(addr); -#ifdef _LP64 case relocInfo::opt_virtual_call_type: return opt_virtual_call_Relocation::spec(); case relocInfo::static_call_type: return static_call_Relocation::spec(); case relocInfo::runtime_call_type: return runtime_call_Relocation::spec(); -#endif case relocInfo::none: return RelocationHolder(); default: @@ -396,12 +392,10 @@ class AddressLiteral VALUE_OBJ_CLASS_SPEC { : _address((address) addr), _rspec(rspec_from_rtype(rtype, (address) addr)) {} -#ifdef _LP64 // 32-bit complains about a multiple declaration for int*. AddressLiteral(intptr_t* addr, relocInfo::relocType rtype = relocInfo::none) : _address((address) addr), _rspec(rspec_from_rtype(rtype, (address) addr)) {} -#endif AddressLiteral(Metadata* addr, relocInfo::relocType rtype = relocInfo::none) : _address((address) addr), @@ -464,16 +458,10 @@ class Argument VALUE_OBJ_CLASS_SPEC { bool _is_in; public: -#ifdef _LP64 enum { n_register_parameters = 6, // only 6 registers may contain integer parameters n_float_register_parameters = 16 // Can have up to 16 floating registers }; -#else - enum { - n_register_parameters = 6 // only 6 registers may contain integer parameters - }; -#endif // creation Argument(int number, bool is_in) : _number(number), _is_in(is_in) {} @@ -489,7 +477,6 @@ class Argument VALUE_OBJ_CLASS_SPEC { // locating register-based arguments: bool is_register() const { return _number < n_register_parameters; } -#ifdef _LP64 // locating Floating Point register-based arguments: bool is_float_register() const { return _number < n_float_register_parameters; } @@ -501,7 +488,6 @@ class Argument VALUE_OBJ_CLASS_SPEC { assert(is_float_register(), "must be a register argument"); return as_FloatRegister(( number() *2 )); } -#endif Register as_register() const { assert(is_register(), "must be a register argument"); @@ -604,15 +590,15 @@ class MacroAssembler : public Assembler { bool check_exception=true // flag which indicates if exception should be checked ); + public: + MacroAssembler(CodeBuffer* code) : Assembler(code) {} + // This routine should emit JVMTI PopFrame and ForceEarlyReturn handling code. // The implementation is only non-empty for the InterpreterMacroAssembler, // as only the interpreter handles and ForceEarlyReturn PopFrame requests. virtual void check_and_handle_popframe(Register scratch_reg); virtual void check_and_handle_earlyret(Register scratch_reg); - public: - MacroAssembler(CodeBuffer* code) : Assembler(code) {} - // Support for NULL-checks // // Generates code that causes a NULL OS exception if the content of reg is NULL. @@ -676,9 +662,6 @@ class MacroAssembler : public Assembler { inline void fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt = relocInfo::none ); inline void fbp( Condition c, bool a, CC cc, Predict p, Label& L ); - // get PC the best way - inline int get_pc( Register d ); - // Sparc shorthands(pp 85, V8 manual, pp 289 V9 manual) inline void cmp( Register s1, Register s2 ); inline void cmp( Register s1, int simm13a ); @@ -1144,7 +1127,7 @@ public: void stop(const char* msg); // prints msg, dumps registers and stops execution void warn(const char* msg); // prints msg, but don't stop void untested(const char* what = ""); - void unimplemented(const char* what = "") { char* b = new char[1024]; jio_snprintf(b, 1024, "unimplemented: %s", what); stop(b); } + void unimplemented(const char* what = ""); void should_not_reach_here() { stop("should not reach here"); } void print_CPU_state(); @@ -1217,9 +1200,7 @@ public: void lushr( Register Rin_high, Register Rin_low, Register Rcount, Register Rout_high, Register Rout_low, Register Rtemp ); -#ifdef _LP64 void lcmp( Register Ra, Register Rb, Register Rresult); -#endif // Load and store values by size and signed-ness void load_sized_value( Address src, Register dst, size_t size_in_bytes, bool is_signed); @@ -1412,7 +1393,7 @@ public: void movitof_revbytes(Register src, FloatRegister dst, Register tmp1, Register tmp2); void movftoi_revbytes(FloatRegister src, Register dst, Register tmp1, Register tmp2); - // CRC32 code for java.util.zip.CRC32::updateBytes0() instrinsic. + // CRC32 code for java.util.zip.CRC32::updateBytes0() intrinsic. void kernel_crc32(Register crc, Register buf, Register len, Register table); // Fold 128-bit data chunk void fold_128bit_crc32(Register xcrc_hi, Register xcrc_lo, Register xK_hi, Register xK_lo, Register xtmp_hi, Register xtmp_lo, Register buf, int offset); @@ -1420,7 +1401,7 @@ public: // Fold 8-bit data void fold_8bit_crc32(Register xcrc, Register table, Register xtmp, Register tmp); void fold_8bit_crc32(Register crc, Register table, Register tmp); - // CRC32C code for java.util.zip.CRC32C::updateBytes/updateDirectByteBuffer instrinsic. + // CRC32C code for java.util.zip.CRC32C::updateBytes/updateDirectByteBuffer intrinsic. void kernel_crc32c(Register crc, Register buf, Register len, Register table); }; diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp index 2f1c949bb7f..679bbd30c29 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -45,19 +45,11 @@ inline void MacroAssembler::pd_patch_instruction(address branch, address target) // Use the right loads/stores for the platform inline void MacroAssembler::ld_ptr( Register s1, Register s2, Register d ) { -#ifdef _LP64 Assembler::ldx(s1, s2, d); -#else - ld( s1, s2, d); -#endif } inline void MacroAssembler::ld_ptr( Register s1, int simm13a, Register d ) { -#ifdef _LP64 Assembler::ldx(s1, simm13a, d); -#else - ld( s1, simm13a, d); -#endif } #ifdef ASSERT @@ -68,35 +60,19 @@ inline void MacroAssembler::ld_ptr( Register s1, ByteSize simm13a, Register d ) #endif inline void MacroAssembler::ld_ptr( Register s1, RegisterOrConstant s2, Register d ) { -#ifdef _LP64 ldx(s1, s2, d); -#else - ld( s1, s2, d); -#endif } inline void MacroAssembler::ld_ptr(const Address& a, Register d, int offset) { -#ifdef _LP64 ldx(a, d, offset); -#else - ld( a, d, offset); -#endif } inline void MacroAssembler::st_ptr( Register d, Register s1, Register s2 ) { -#ifdef _LP64 Assembler::stx(d, s1, s2); -#else - st( d, s1, s2); -#endif } inline void MacroAssembler::st_ptr( Register d, Register s1, int simm13a ) { -#ifdef _LP64 Assembler::stx(d, s1, simm13a); -#else - st( d, s1, simm13a); -#endif } #ifdef ASSERT @@ -107,84 +83,44 @@ inline void MacroAssembler::st_ptr( Register d, Register s1, ByteSize simm13a ) #endif inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterOrConstant s2 ) { -#ifdef _LP64 stx(d, s1, s2); -#else - st( d, s1, s2); -#endif } inline void MacroAssembler::st_ptr(Register d, const Address& a, int offset) { -#ifdef _LP64 stx(d, a, offset); -#else - st( d, a, offset); -#endif } // Use the right loads/stores for the platform inline void MacroAssembler::ld_long( Register s1, Register s2, Register d ) { -#ifdef _LP64 Assembler::ldx(s1, s2, d); -#else - Assembler::ldd(s1, s2, d); -#endif } inline void MacroAssembler::ld_long( Register s1, int simm13a, Register d ) { -#ifdef _LP64 Assembler::ldx(s1, simm13a, d); -#else - Assembler::ldd(s1, simm13a, d); -#endif } inline void MacroAssembler::ld_long( Register s1, RegisterOrConstant s2, Register d ) { -#ifdef _LP64 ldx(s1, s2, d); -#else - ldd(s1, s2, d); -#endif } inline void MacroAssembler::ld_long(const Address& a, Register d, int offset) { -#ifdef _LP64 ldx(a, d, offset); -#else - ldd(a, d, offset); -#endif } inline void MacroAssembler::st_long( Register d, Register s1, Register s2 ) { -#ifdef _LP64 Assembler::stx(d, s1, s2); -#else - Assembler::std(d, s1, s2); -#endif } inline void MacroAssembler::st_long( Register d, Register s1, int simm13a ) { -#ifdef _LP64 Assembler::stx(d, s1, simm13a); -#else - Assembler::std(d, s1, simm13a); -#endif } inline void MacroAssembler::st_long( Register d, Register s1, RegisterOrConstant s2 ) { -#ifdef _LP64 stx(d, s1, s2); -#else - std(d, s1, s2); -#endif } inline void MacroAssembler::st_long( Register d, const Address& a, int offset ) { -#ifdef _LP64 stx(d, a, offset); -#else - std(d, a, offset); -#endif } inline void MacroAssembler::stbool(Register d, const Address& a) { stb(d, a); } @@ -207,45 +143,25 @@ inline void MacroAssembler::casx( Register s1, Register s2, Register d) { casxa( // Functions for isolating 64 bit atomic swaps for LP64 // cas_ptr will perform cas for 32 bit VM's and casx for 64 bit VM's inline void MacroAssembler::cas_ptr( Register s1, Register s2, Register d) { -#ifdef _LP64 casx( s1, s2, d ); -#else - cas( s1, s2, d ); -#endif } // Functions for isolating 64 bit shifts for LP64 inline void MacroAssembler::sll_ptr( Register s1, Register s2, Register d ) { -#ifdef _LP64 Assembler::sllx(s1, s2, d); -#else - Assembler::sll( s1, s2, d); -#endif } inline void MacroAssembler::sll_ptr( Register s1, int imm6a, Register d ) { -#ifdef _LP64 Assembler::sllx(s1, imm6a, d); -#else - Assembler::sll( s1, imm6a, d); -#endif } inline void MacroAssembler::srl_ptr( Register s1, Register s2, Register d ) { -#ifdef _LP64 Assembler::srlx(s1, s2, d); -#else - Assembler::srl( s1, s2, d); -#endif } inline void MacroAssembler::srl_ptr( Register s1, int imm6a, Register d ) { -#ifdef _LP64 Assembler::srlx(s1, imm6a, d); -#else - Assembler::srl( s1, imm6a, d); -#endif } inline void MacroAssembler::sll_ptr( Register s1, RegisterOrConstant s2, Register d ) { @@ -269,7 +185,8 @@ inline void MacroAssembler::br( Condition c, bool a, Predict p, address d, reloc } inline void MacroAssembler::br( Condition c, bool a, Predict p, Label& L ) { - insert_nop_after_cbcond(); + // See note[+] on 'avoid_pipeline_stalls()', in "assembler_sparc.inline.hpp". + avoid_pipeline_stall(); br(c, a, p, target(L)); } @@ -277,15 +194,11 @@ inline void MacroAssembler::br( Condition c, bool a, Predict p, Label& L ) { // Branch that tests either xcc or icc depending on the // architecture compiled (LP64 or not) inline void MacroAssembler::brx( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) { -#ifdef _LP64 Assembler::bp(c, a, xcc, p, d, rt); -#else - MacroAssembler::br(c, a, p, d, rt); -#endif } inline void MacroAssembler::brx( Condition c, bool a, Predict p, Label& L ) { - insert_nop_after_cbcond(); + avoid_pipeline_stall(); brx(c, a, p, target(L)); } @@ -307,7 +220,7 @@ inline void MacroAssembler::fb( Condition c, bool a, Predict p, address d, reloc } inline void MacroAssembler::fb( Condition c, bool a, Predict p, Label& L ) { - insert_nop_after_cbcond(); + avoid_pipeline_stall(); fb(c, a, p, target(L)); } @@ -338,7 +251,6 @@ inline void MacroAssembler::call( address d, relocInfo::relocType rt ) { } inline void MacroAssembler::call( address d, RelocationHolder const& rspec ) { -#ifdef _LP64 intptr_t disp; // NULL is ok because it will be relocated later. // Must change NULL to a reachable address in order to @@ -355,18 +267,14 @@ inline void MacroAssembler::call( address d, RelocationHolder const& rspec ) { } else { Assembler::call(d, rspec); } -#else - Assembler::call( d, rspec ); -#endif } -inline void MacroAssembler::call( Label& L, relocInfo::relocType rt ) { - insert_nop_after_cbcond(); - MacroAssembler::call( target(L), rt); +inline void MacroAssembler::call( Label& L, relocInfo::relocType rt ) { + avoid_pipeline_stall(); + MacroAssembler::call(target(L), rt); } - inline void MacroAssembler::callr( Register s1, Register s2 ) { jmpl( s1, s2, O7 ); } inline void MacroAssembler::callr( Register s1, int simm13a, RelocationHolder const& rspec ) { jmpl( s1, simm13a, O7, rspec); } @@ -396,13 +304,6 @@ inline void MacroAssembler::retl( bool trace ) { } } -// clobbers o7 on V8!! -// returns delta from gotten pc to addr after -inline int MacroAssembler::get_pc( Register d ) { - int x = offset(); - rdpc(d); - return offset() - x; -} inline void MacroAssembler::cmp( Register s1, Register s2 ) { subcc( s1, s2, G0 ); } inline void MacroAssembler::cmp( Register s1, int simm13a ) { subcc( s1, simm13a, G0 ); } @@ -414,12 +315,7 @@ inline void MacroAssembler::cmp( Register s1, int simm13a ) { subcc( s1, simm13 // 2 instructions. All PCs in the CodeCache are within 2 Gig of each other. inline intptr_t MacroAssembler::load_pc_address( Register reg, int bytes_to_skip ) { intptr_t thepc = (intptr_t)pc() + 2*BytesPerInstWord + bytes_to_skip; -#ifdef _LP64 Unimplemented(); -#else - Assembler::sethi( thepc & ~0x3ff, reg, internal_word_Relocation::spec((address)thepc)); - add(reg, thepc & 0x3ff, reg, internal_word_Relocation::spec((address)thepc)); -#endif return thepc; } @@ -554,7 +450,6 @@ inline void MacroAssembler::store_ptr_argument( Register s, Argument& a ) { } -#ifdef _LP64 inline void MacroAssembler::store_float_argument( FloatRegister s, Argument& a ) { if (a.is_float_register()) // V9 ABI has F1, F3, F5 are used to pass instead of O0, O1, O2 @@ -579,7 +474,6 @@ inline void MacroAssembler::store_long_argument( Register s, Argument& a ) { else stx(s, a.as_address()); } -#endif inline void MacroAssembler::round_to( Register r, int modulus ) { assert_not_delayed(); @@ -640,22 +534,13 @@ inline void MacroAssembler::clrx( Register s1, int simm13a) { stx( G0, s1, simm1 inline void MacroAssembler::clruw( Register s, Register d ) { srl( s, G0, d); } inline void MacroAssembler::clruwu( Register d ) { srl( d, G0, d); } -#ifdef _LP64 // Make all 32 bit loads signed so 64 bit registers maintain proper sign inline void MacroAssembler::ld( Register s1, Register s2, Register d) { ldsw( s1, s2, d); } inline void MacroAssembler::ld( Register s1, int simm13a, Register d) { ldsw( s1, simm13a, d); } -#else -inline void MacroAssembler::ld( Register s1, Register s2, Register d) { lduw( s1, s2, d); } -inline void MacroAssembler::ld( Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); } -#endif #ifdef ASSERT // ByteSize is only a class when ASSERT is defined, otherwise it's an int. -# ifdef _LP64 inline void MacroAssembler::ld(Register s1, ByteSize simm13a, Register d) { ldsw( s1, in_bytes(simm13a), d); } -# else -inline void MacroAssembler::ld(Register s1, ByteSize simm13a, Register d) { lduw( s1, in_bytes(simm13a), d); } -# endif #endif inline void MacroAssembler::ld( const Address& a, Register d, int offset) { diff --git a/hotspot/src/cpu/sparc/vm/memset_with_concurrent_readers_sparc.cpp b/hotspot/src/cpu/sparc/vm/memset_with_concurrent_readers_sparc.cpp index adacfda4ae6..e442d8f9c41 100644 --- a/hotspot/src/cpu/sparc/vm/memset_with_concurrent_readers_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/memset_with_concurrent_readers_sparc.cpp @@ -26,6 +26,7 @@ #include "gc/shared/memset_with_concurrent_readers.hpp" #include "runtime/prefetch.inline.hpp" +#include "utilities/align.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" @@ -86,7 +87,7 @@ void memset_with_concurrent_readers(void* to, int value, size_t size) { void* end = static_cast(to) + size; if (size >= (size_t)BytesPerWord) { // Fill any partial word prefix. - uintx* aligned_to = static_cast(align_ptr_up(to, BytesPerWord)); + uintx* aligned_to = static_cast(align_up(to, BytesPerWord)); fill_subword(to, aligned_to, value); // Compute fill word. @@ -97,7 +98,7 @@ void memset_with_concurrent_readers(void* to, int value, size_t size) { xvalue |= (xvalue << 16); xvalue |= (xvalue << 32); - uintx* aligned_end = static_cast(align_ptr_down(end, BytesPerWord)); + uintx* aligned_end = static_cast(align_down(end, BytesPerWord)); assert(aligned_to <= aligned_end, "invariant"); // for ( ; aligned_to < aligned_end; ++aligned_to) { diff --git a/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp b/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp deleted file mode 100644 index cc0141c283e..00000000000 --- a/hotspot/src/cpu/sparc/vm/metaspaceShared_sparc.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.inline.hpp" -#include "asm/codeBuffer.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - Label common_code; - for (int i = 0; i < vtbl_list_size; ++i) { - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*)masm->pc(); - __ save(SP, -256, SP); - int offset = (i << 8) + j; - Register src = G0; - if (!Assembler::is_simm13(offset)) { - __ sethi(offset, L0); - src = L0; - offset = offset & ((1 << 10) - 1); - } - __ brx(Assembler::always, false, Assembler::pt, common_code); - - // Load L0 with a value indicating vtable/offset pair. - // -- bits[ 7..0] (8 bits) which virtual method in table? - // -- bits[13..8] (6 bits) which virtual method table? - __ delayed()->or3(src, offset, L0); - } - } - - __ bind(common_code); - - // Expecting to be called with the "this" pointer in O0/I0 (where - // "this" is a Klass object). In addition, L0 was set (above) to - // identify the method and table. - - // Look up the correct vtable pointer. - - __ set((intptr_t)vtbl_list, L2); // L2 = address of new vtable list. - __ srl(L0, 8, L3); // Isolate L3 = vtable identifier. - __ sll(L3, LogBytesPerWord, L3); - __ ld_ptr(L2, L3, L3); // L3 = new (correct) vtable pointer. - __ st_ptr(L3, Address(I0, 0)); // Save correct vtable ptr in entry. - - // Restore registers and jump to the correct method; - - __ and3(L0, 255, L4); // Isolate L3 = method offset;. - __ sll(L4, LogBytesPerWord, L4); - __ ld_ptr(L3, L4, L4); // Get address of correct virtual method - __ jmpl(L4, 0, G0); // Jump to correct method. - __ delayed()->restore(); // Restore registers. - - __ flush(); - *mc_top = (char*)__ pc(); - - guarantee(*mc_top <= mc_end, "Insufficient space for method wrappers."); -} diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp index f93dbf17212..37ac1024f4e 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ -29,6 +29,7 @@ #include "interpreter/interp_masm.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" +#include "prims/jvm.h" #include "prims/methodHandles.hpp" #define __ _masm-> @@ -71,7 +72,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register temp_reg, Register temp2_reg, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); bool did_save = false; if (temp_reg == noreg || temp2_reg == noreg) { temp_reg = L1; @@ -181,8 +182,9 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, __ verify_oop(method_temp); __ load_heap_oop(Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())), method_temp); __ verify_oop(method_temp); - // the following assumes that a Method* is normally compressed in the vmtarget field: - __ ld_ptr( Address(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())), method_temp); + __ load_heap_oop(Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())), method_temp); + __ verify_oop(method_temp); + __ ld_ptr( Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())), method_temp); if (VerifyMethodHandles && !for_compiler_entry) { // make sure recv is already on stack @@ -332,7 +334,8 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes())); Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes())); - Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())); + Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())); + Address vmtarget_method( G5_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())); Register temp1_recv_klass = temp1; if (iid != vmIntrinsics::_linkToStatic) { @@ -384,14 +387,16 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp2); } - __ ld_ptr(member_vmtarget, G5_method); + __ load_heap_oop(member_vmtarget, G5_method); + __ ld_ptr(vmtarget_method, G5_method); break; case vmIntrinsics::_linkToStatic: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp2); } - __ ld_ptr(member_vmtarget, G5_method); + __ load_heap_oop(member_vmtarget, G5_method); + __ ld_ptr(vmtarget_method, G5_method); break; case vmIntrinsics::_linkToVirtual: diff --git a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.hpp b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.hpp index d58e7d75cd0..6638a194dec 100644 --- a/hotspot/src/cpu/sparc/vm/methodHandles_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/methodHandles_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ // Adapters enum /* platform_dependent_constants */ { - adapter_code_size = NOT_LP64(23000 DEBUG_ONLY(+ 40000)) LP64_ONLY(35000 DEBUG_ONLY(+ 50000)) + adapter_code_size = 35000 DEBUG_ONLY(+ 50000) }; // Additional helper methods for MethodHandles code generation: diff --git a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp index 103c712cee4..950619dacb4 100644 --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -236,8 +236,6 @@ void NativeCall::test() { //------------------------------------------------------------------- -#ifdef _LP64 - void NativeFarCall::set_destination(address dest) { // Address materialized in the instruction stream, so nothing to do. return; @@ -290,8 +288,6 @@ void NativeFarCall::test() { } // End code for unit testing implementation of NativeFarCall class -#endif // _LP64 - //------------------------------------------------------------------- @@ -304,18 +300,9 @@ void NativeMovConstReg::verify() { // verify the pattern "sethi %hi22(imm), reg ; add reg, %lo10(imm), reg" Register rd = inv_rd(i0); -#ifndef _LP64 - if (!(is_op2(i0, Assembler::sethi_op2) && rd != G0 && - is_op3(i1, Assembler::add_op3, Assembler::arith_op) && - inv_immed(i1) && (unsigned)get_simm13(i1) < (1 << 10) && - rd == inv_rs1(i1) && rd == inv_rd(i1))) { - fatal("not a set_metadata"); - } -#else if (!is_op2(i0, Assembler::sethi_op2) && rd != G0 ) { fatal("not a set_metadata"); } -#endif } @@ -324,23 +311,13 @@ void NativeMovConstReg::print() { } -#ifdef _LP64 intptr_t NativeMovConstReg::data() const { return data64(addr_at(sethi_offset), long_at(add_offset)); } -#else -intptr_t NativeMovConstReg::data() const { - return data32(long_at(sethi_offset), long_at(add_offset)); -} -#endif void NativeMovConstReg::set_data(intptr_t x) { -#ifdef _LP64 set_data64_sethi(addr_at(sethi_offset), x); -#else - set_long_at(sethi_offset, set_data32_sethi( long_at(sethi_offset), x)); -#endif set_long_at(add_offset, set_data32_simm13( long_at(add_offset), x)); // also store the value into an oop_Relocation cell, if any @@ -508,20 +485,12 @@ void NativeMovConstRegPatching::print() { int NativeMovConstRegPatching::data() const { -#ifdef _LP64 return data64(addr_at(sethi_offset), long_at(add_offset)); -#else - return data32(long_at(sethi_offset), long_at(add_offset)); -#endif } void NativeMovConstRegPatching::set_data(int x) { -#ifdef _LP64 set_data64_sethi(addr_at(sethi_offset), x); -#else - set_long_at(sethi_offset, set_data32_sethi(long_at(sethi_offset), x)); -#endif set_long_at(add_offset, set_data32_simm13(long_at(add_offset), x)); // also store the value into an oop_Relocation cell, if any @@ -758,21 +727,12 @@ void NativeJump::verify() { assert((int)jmpl_offset == (int)NativeMovConstReg::add_offset, "sethi size ok"); // verify the pattern "sethi %hi22(imm), treg ; jmpl treg, %lo10(imm), lreg" Register rd = inv_rd(i0); -#ifndef _LP64 - if (!(is_op2(i0, Assembler::sethi_op2) && rd != G0 && - (is_op3(i1, Assembler::jmpl_op3, Assembler::arith_op)) && - inv_immed(i1) && (unsigned)get_simm13(i1) < (1 << 10) && - rd == inv_rs1(i1))) { - fatal("not a jump_to instruction"); - } -#else // In LP64, the jump instruction location varies for non relocatable // jumps, for example is could be sethi, xor, jmp instead of the // 7 instructions for sethi. So let's check sethi only. if (!is_op2(i0, Assembler::sethi_op2) && rd != G0 ) { fatal("not a jump_to instruction"); } -#endif } diff --git a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp index d0582f34265..c2a27394a75 100644 --- a/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/nativeInst_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -67,11 +67,8 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC { bool is_illegal(); bool is_zombie() { int x = long_at(0); - return is_op3(x, - Assembler::ldsw_op3, - Assembler::ldst_op) - && Assembler::inv_rs1(x) == G0 - && Assembler::inv_rd(x) == O7; + return (is_op3(x, Assembler::ldsw_op3, Assembler::ldst_op) && + inv_rs1(x) == G0 && inv_rd(x) == O7); } bool is_ic_miss_trap(); // Inline-cache uses a trap to detect a miss bool is_return() { @@ -121,11 +118,7 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC { bool is_safepoint_poll() { int x = long_at(0); -#ifdef _LP64 return is_op3(x, Assembler::ldx_op3, Assembler::ldst_op) && -#else - return is_op3(x, Assembler::lduw_op3, Assembler::ldst_op) && -#endif (inv_rd(x) == G0) && (inv_immed(x) ? Assembler::inv_simm13(x) == 0 : inv_rs2(x) == G0); } @@ -133,29 +126,11 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC { bool is_load_store_with_small_offset(Register reg); public: -#ifdef ASSERT - static int rdpc_instruction() { return Assembler::op(Assembler::arith_op ) | Assembler::op3(Assembler::rdreg_op3) | Assembler::u_field(5, 18, 14) | Assembler::rd(O7); } -#else - // Temporary fix: in optimized mode, u_field is a macro for efficiency reasons (see Assembler::u_field) - needs to be fixed - static int rdpc_instruction() { return Assembler::op(Assembler::arith_op ) | Assembler::op3(Assembler::rdreg_op3) | u_field(5, 18, 14) | Assembler::rd(O7); } -#endif static int nop_instruction() { return Assembler::op(Assembler::branch_op) | Assembler::op2(Assembler::sethi_op2); } static int illegal_instruction(); // the output of __ breakpoint_trap() static int call_instruction(address destination, address pc) { return Assembler::op(Assembler::call_op) | Assembler::wdisp((intptr_t)destination, (intptr_t)pc, 30); } - static int branch_instruction(Assembler::op2s op2val, Assembler::Condition c, bool a) { - return Assembler::op(Assembler::branch_op) | Assembler::op2(op2val) | Assembler::annul(a) | Assembler::cond(c); - } - - static int op3_instruction(Assembler::ops opval, Register rd, Assembler::op3s op3val, Register rs1, int simm13a) { - return Assembler::op(opval) | Assembler::rd(rd) | Assembler::op3(op3val) | Assembler::rs1(rs1) | Assembler::immed(true) | Assembler::simm(simm13a, 13); - } - - static int sethi_instruction(Register rd, int imm22a) { - return Assembler::op(Assembler::branch_op) | Assembler::rd(rd) | Assembler::op2(Assembler::sethi_op2) | Assembler::hi22(imm22a); - } - - protected: +protected: address addr_at(int offset) const { return address(this) + offset; } int long_at(int offset) const { return *(int*)addr_at(offset); } void set_long_at(int offset, int i); /* deals with I-cache */ @@ -432,22 +407,6 @@ class NativeCallReg: public NativeInstruction { // instructions in the sparcv9 vm. Used to call native methods which may be loaded // anywhere in the address space, possibly out of reach of a call instruction. -#ifndef _LP64 - -// On 32-bit systems, a far call is the same as a near one. -class NativeFarCall; -inline NativeFarCall* nativeFarCall_at(address instr); -class NativeFarCall : public NativeCall { -public: - friend inline NativeFarCall* nativeFarCall_at(address instr) { return (NativeFarCall*)nativeCall_at(instr); } - friend NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination = NULL) - { return (NativeFarCall*)nativeCall_overwriting_at(instr, destination); } - friend NativeFarCall* nativeFarCall_before(address return_address) - { return (NativeFarCall*)nativeCall_before(return_address); } -}; - -#else - // The format of this extended-range call is: // jumpl_to addr, lreg // == sethi %hi54(addr), O7 ; jumpl O7, %lo10(addr), O7 ; @@ -515,7 +474,6 @@ class NativeFarCall: public NativeInstruction { static void replace_mt_safe(address instr_addr, address code_buffer); }; -#endif // _LP64 // An interface for accessing/manipulating 32 bit native set_metadata imm, reg instructions // (used to manipulate inlined data references, etc.) @@ -567,13 +525,8 @@ class NativeMovConstReg: public NativeInstruction { public: enum Sparc_specific_constants { sethi_offset = 0, -#ifdef _LP64 add_offset = 7 * BytesPerInstWord, instruction_size = 8 * BytesPerInstWord -#else - add_offset = 4, - instruction_size = 8 -#endif }; address instruction_address() const { return addr_at(0); } @@ -626,11 +579,7 @@ inline NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address); public: enum Sparc_specific_constants { sethi_offset = 0, -#ifdef _LP64 nop_offset = 7 * BytesPerInstWord, -#else - nop_offset = sethi_offset + BytesPerInstWord, -#endif add_offset = nop_offset + BytesPerInstWord, instruction_size = add_offset + BytesPerInstWord }; @@ -705,11 +654,7 @@ class NativeMovRegMem: public NativeInstruction { offset_width = 13, sethi_offset = 0, -#ifdef _LP64 add_offset = 7 * BytesPerInstWord, -#else - add_offset = 4, -#endif ldst_offset = add_offset + BytesPerInstWord }; bool is_immediate() const { @@ -720,11 +665,7 @@ class NativeMovRegMem: public NativeInstruction { address instruction_address() const { return addr_at(0); } address next_instruction_address() const { -#ifdef _LP64 return addr_at(is_immediate() ? 4 : (7 * BytesPerInstWord)); -#else - return addr_at(is_immediate() ? 4 : 12); -#endif } intptr_t offset() const { return is_immediate()? inv_simm(long_at(0), offset_width) : @@ -777,19 +718,13 @@ class NativeJump: public NativeInstruction { public: enum Sparc_specific_constants { sethi_offset = 0, -#ifdef _LP64 jmpl_offset = 7 * BytesPerInstWord, instruction_size = 9 * BytesPerInstWord // includes delay slot -#else - jmpl_offset = 1 * BytesPerInstWord, - instruction_size = 3 * BytesPerInstWord // includes delay slot -#endif }; address instruction_address() const { return addr_at(0); } address next_instruction_address() const { return addr_at(instruction_size); } -#ifdef _LP64 address jump_destination() const { return (address) data64(instruction_address(), long_at(jmpl_offset)); } @@ -797,15 +732,6 @@ class NativeJump: public NativeInstruction { set_data64_sethi( instruction_address(), (intptr_t)dest); set_long_at(jmpl_offset, set_data32_simm13( long_at(jmpl_offset), (intptr_t)dest)); } -#else - address jump_destination() const { - return (address) data32(long_at(sethi_offset), long_at(jmpl_offset)); - } - void set_jump_destination(address dest) { - set_long_at(sethi_offset, set_data32_sethi( long_at(sethi_offset), (intptr_t)dest)); - set_long_at(jmpl_offset, set_data32_simm13( long_at(jmpl_offset), (intptr_t)dest)); - } -#endif // Creation friend inline NativeJump* nativeJump_at(address address) { diff --git a/hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp b/hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp index 8fd22e24670..98cfb72c405 100644 --- a/hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/register_definitions_sparc.cpp @@ -166,7 +166,6 @@ REGISTER_DEFINITION(Register, I5_savedSP); REGISTER_DEFINITION(Register, O5_savedSP); REGISTER_DEFINITION(Register, IdispatchAddress); REGISTER_DEFINITION(Register, ImethodDataPtr); -REGISTER_DEFINITION(Register, IdispatchTables); REGISTER_DEFINITION(Register, Lmethod); REGISTER_DEFINITION(Register, Llocals); REGISTER_DEFINITION(Register, Oexception); diff --git a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp index 9c70bd0ef4d..f75588c8538 100644 --- a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -93,7 +93,6 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { case Assembler::branch_op: { -#ifdef _LP64 jint inst2; guarantee(Assembler::inv_op2(inst)==Assembler::sethi_op2, "must be sethi"); if (format() != 0) { @@ -121,17 +120,6 @@ void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) { } else { ip->set_data64_sethi( ip->addr_at(0), (intptr_t)x ); } -#else - guarantee(Assembler::inv_op2(inst)==Assembler::sethi_op2, "must be sethi"); - inst &= ~Assembler::hi22( -1); - inst |= Assembler::hi22((intptr_t)x); - // (ignore offset; it doesn't play into the sethi) - if (verify_only) { - guarantee(ip->long_at(0) == inst, "instructions must match"); - } else { - ip->set_long_at(0, inst); - } -#endif } break; diff --git a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.hpp b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.hpp index a2d3b2c3928..26daae3757b 100644 --- a/hotspot/src/cpu/sparc/vm/relocInfo_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/relocInfo_sparc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -34,12 +34,8 @@ // There is no need for format bits; the instructions are // sufficiently self-identifying. -#ifndef _LP64 - format_width = 0 -#else // Except narrow oops in 64-bits VM. format_width = 1 -#endif }; diff --git a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp index 613e662d65c..4f217e33ac6 100644 --- a/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/sharedRuntime_sparc.cpp @@ -33,6 +33,7 @@ #include "oops/compiledICHolder.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/align.hpp" #include "vmreg_sparc.inline.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" @@ -77,7 +78,7 @@ class RegisterSaver { call_args_area = frame::register_save_words_sp_offset + frame::memory_parameter_word_sp_offset*wordSize, // Make sure save locations are always 8 byte aligned. - // can't use round_to because it doesn't produce compile time constant + // can't use align_up because it doesn't produce compile time constant start_of_extra_save_area = ((call_args_area + 7) & ~7), g1_offset = start_of_extra_save_area, // g-regs needing saving g3_offset = g1_offset+8, @@ -119,7 +120,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ // (as the stub's I's) when the runtime routine called by the stub creates its frame. int i; // Always make the frame size 16 byte aligned. - int frame_size = round_to(additional_frame_words + register_save_size, 16); + int frame_size = align_up(additional_frame_words + register_save_size, 16); // OopMap frame size is in c2 stack slots (sizeof(jint)) not bytes or words int frame_size_in_slots = frame_size / sizeof(jint); // CodeBlob frame size is in words. @@ -127,56 +128,10 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ // OopMap* map = new OopMap(*total_frame_words, 0); OopMap* map = new OopMap(frame_size_in_slots, 0); -#if !defined(_LP64) - - // Save 64-bit O registers; they will get their heads chopped off on a 'save'. - __ stx(O0, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8); - __ stx(O1, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8); - __ stx(O2, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+2*8); - __ stx(O3, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+3*8); - __ stx(O4, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+4*8); - __ stx(O5, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+5*8); -#endif /* _LP64 */ - __ save(SP, -frame_size, SP); -#ifndef _LP64 - // Reload the 64 bit Oregs. Although they are now Iregs we load them - // to Oregs here to avoid interrupts cutting off their heads - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8, O0); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8, O1); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+2*8, O2); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+3*8, O3); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+4*8, O4); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+5*8, O5); - - __ stx(O0, SP, o0_offset+STACK_BIAS); - map->set_callee_saved(VMRegImpl::stack2reg((o0_offset + 4)>>2), O0->as_VMReg()); - - __ stx(O1, SP, o1_offset+STACK_BIAS); - - map->set_callee_saved(VMRegImpl::stack2reg((o1_offset + 4)>>2), O1->as_VMReg()); - - __ stx(O2, SP, o2_offset+STACK_BIAS); - map->set_callee_saved(VMRegImpl::stack2reg((o2_offset + 4)>>2), O2->as_VMReg()); - - __ stx(O3, SP, o3_offset+STACK_BIAS); - map->set_callee_saved(VMRegImpl::stack2reg((o3_offset + 4)>>2), O3->as_VMReg()); - - __ stx(O4, SP, o4_offset+STACK_BIAS); - map->set_callee_saved(VMRegImpl::stack2reg((o4_offset + 4)>>2), O4->as_VMReg()); - - __ stx(O5, SP, o5_offset+STACK_BIAS); - map->set_callee_saved(VMRegImpl::stack2reg((o5_offset + 4)>>2), O5->as_VMReg()); -#endif /* _LP64 */ - - -#ifdef _LP64 int debug_offset = 0; -#else - int debug_offset = 4; -#endif // Save the G's __ stx(G1, SP, g1_offset+STACK_BIAS); map->set_callee_saved(VMRegImpl::stack2reg((g1_offset + debug_offset)>>2), G1->as_VMReg()); @@ -192,18 +147,6 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ // This is really a waste but we'll keep things as they were for now if (true) { -#ifndef _LP64 - map->set_callee_saved(VMRegImpl::stack2reg((o0_offset)>>2), O0->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((o1_offset)>>2), O1->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((o2_offset)>>2), O2->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((o3_offset)>>2), O3->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((o4_offset)>>2), O4->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((o5_offset)>>2), O5->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((g1_offset)>>2), G1->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((g3_offset)>>2), G3->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((g4_offset)>>2), G4->as_VMReg()->next()); - map->set_callee_saved(VMRegImpl::stack2reg((g5_offset)>>2), G5->as_VMReg()->next()); -#endif /* _LP64 */ } @@ -250,70 +193,22 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm) { __ ldx(SP, g4_offset+STACK_BIAS, G4); __ ldx(SP, g5_offset+STACK_BIAS, G5); - -#if !defined(_LP64) - // Restore the 64-bit O's. - __ ldx(SP, o0_offset+STACK_BIAS, O0); - __ ldx(SP, o1_offset+STACK_BIAS, O1); - __ ldx(SP, o2_offset+STACK_BIAS, O2); - __ ldx(SP, o3_offset+STACK_BIAS, O3); - __ ldx(SP, o4_offset+STACK_BIAS, O4); - __ ldx(SP, o5_offset+STACK_BIAS, O5); - - // And temporarily place them in TLS - - __ stx(O0, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8); - __ stx(O1, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8); - __ stx(O2, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+2*8); - __ stx(O3, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+3*8); - __ stx(O4, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+4*8); - __ stx(O5, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+5*8); -#endif /* _LP64 */ - // Restore flags __ ldxfsr(SP, fsr_offset+STACK_BIAS); __ restore(); -#if !defined(_LP64) - // Now reload the 64bit Oregs after we've restore the window. - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8, O0); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8, O1); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+2*8, O2); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+3*8, O3); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+4*8, O4); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+5*8, O5); -#endif /* _LP64 */ - } // Pop the current frame and restore the registers that might be holding // a result. void RegisterSaver::restore_result_registers(MacroAssembler* masm) { -#if !defined(_LP64) - // 32bit build returns longs in G1 - __ ldx(SP, g1_offset+STACK_BIAS, G1); - - // Retrieve the 64-bit O's. - __ ldx(SP, o0_offset+STACK_BIAS, O0); - __ ldx(SP, o1_offset+STACK_BIAS, O1); - // and save to TLS - __ stx(O0, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8); - __ stx(O1, G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8); -#endif /* _LP64 */ - __ ldf(FloatRegisterImpl::D, SP, d00_offset+STACK_BIAS, as_FloatRegister(0)); __ restore(); -#if !defined(_LP64) - // Now reload the 64bit Oregs after we've restore the window. - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+0*8, O0); - __ ldx(G2_thread, JavaThread::o_reg_temps_offset_in_bytes()+1*8, O1); -#endif /* _LP64 */ - } // Is vector's size (in bytes) bigger than a size saved by default? @@ -410,11 +305,6 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt, case T_CHAR: case T_BYTE: case T_BOOLEAN: -#ifndef _LP64 - case T_OBJECT: - case T_ARRAY: - case T_ADDRESS: // Used, e.g., in slow-path locking for the lock's stack address -#endif // _LP64 if (int_reg < int_reg_max) { Register r = is_outgoing ? as_oRegister(int_reg++) : as_iRegister(int_reg++); regs[i].set1(r->as_VMReg()); @@ -423,7 +313,6 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt, } break; -#ifdef _LP64 case T_LONG: assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting VOID in other half"); // fall-through @@ -434,21 +323,11 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt, Register r = is_outgoing ? as_oRegister(int_reg++) : as_iRegister(int_reg++); regs[i].set2(r->as_VMReg()); } else { - slot = round_to(slot, 2); // align + slot = align_up(slot, 2); // align regs[i].set2(VMRegImpl::stack2reg(slot)); slot += 2; } break; -#else - case T_LONG: - assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting VOID in other half"); - // On 32-bit SPARC put longs always on the stack to keep the pressure off - // integer argument registers. They should be used for oops. - slot = round_to(slot, 2); // align - regs[i].set2(VMRegImpl::stack2reg(slot)); - slot += 2; -#endif - break; case T_FLOAT: if (flt_reg < flt_reg_max) { @@ -461,13 +340,13 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt, case T_DOUBLE: assert((i + 1) < total_args_passed && sig_bt[i+1] == T_VOID, "expecting half"); - if (round_to(flt_reg, 2) + 1 < flt_reg_max) { - flt_reg = round_to(flt_reg, 2); // align + if (align_up(flt_reg, 2) + 1 < flt_reg_max) { + flt_reg = align_up(flt_reg, 2); // align FloatRegister r = as_FloatRegister(flt_reg); regs[i].set2(r->as_VMReg()); flt_reg += 2; } else { - slot = round_to(slot, 2); // align + slot = align_up(slot, 2); // align regs[i].set2(VMRegImpl::stack2reg(slot)); slot += 2; } @@ -554,7 +433,6 @@ void AdapterGenerator::patch_callers_callsite() { // The longs must go to the stack by hand since in the 32 bit build they can be trashed by window ops. -#ifdef _LP64 // mov(s,d) __ mov(G1, L1); __ mov(G4, L4); @@ -571,20 +449,6 @@ void AdapterGenerator::patch_callers_callsite() { __ mov(L1, G1); __ mov(L4, G4); __ mov(L5, G5_method); -#else - __ stx(G1, FP, -8 + STACK_BIAS); - __ stx(G4, FP, -16 + STACK_BIAS); - __ mov(G5_method, L5); - __ mov(G5_method, O0); // VM needs target method - __ mov(I7, O1); // VM needs caller's callsite - // Must be a leaf call... - __ call(CAST_FROM_FN_PTR(address, SharedRuntime::fixup_callers_callsite), relocInfo::runtime_call_type); - __ delayed()->mov(G2_thread, L7_thread_cache); - __ mov(L7_thread_cache, G2_thread); - __ ldx(FP, -8 + STACK_BIAS, G1); - __ ldx(FP, -16 + STACK_BIAS, G4); - __ mov(L5, G5_method); -#endif /* _LP64 */ __ restore(); // Restore args __ bind(L); @@ -605,28 +469,9 @@ RegisterOrConstant AdapterGenerator::next_arg_slot(const int st_off) { // Stores long into offset pointed to by base void AdapterGenerator::store_c2i_long(Register r, Register base, const int st_off, bool is_stack) { -#ifdef _LP64 // In V9, longs are given 2 64-bit slots in the interpreter, but the // data is passed in only 1 slot. __ stx(r, base, next_arg_slot(st_off)); -#else -#ifdef COMPILER2 - // Misaligned store of 64-bit data - __ stw(r, base, arg_slot(st_off)); // lo bits - __ srlx(r, 32, r); - __ stw(r, base, next_arg_slot(st_off)); // hi bits -#else - if (is_stack) { - // Misaligned store of 64-bit data - __ stw(r, base, arg_slot(st_off)); // lo bits - __ srlx(r, 32, r); - __ stw(r, base, next_arg_slot(st_off)); // hi bits - } else { - __ stw(r->successor(), base, arg_slot(st_off) ); // lo bits - __ stw(r , base, next_arg_slot(st_off)); // hi bits - } -#endif // COMPILER2 -#endif // _LP64 } void AdapterGenerator::store_c2i_object(Register r, Register base, @@ -642,15 +487,9 @@ void AdapterGenerator::store_c2i_int(Register r, Register base, // Stores into offset pointed to by base void AdapterGenerator::store_c2i_double(VMReg r_2, VMReg r_1, Register base, const int st_off) { -#ifdef _LP64 // In V9, doubles are given 2 64-bit slots in the interpreter, but the // data is passed in only 1 slot. __ stf(FloatRegisterImpl::D, r_1->as_FloatRegister(), base, next_arg_slot(st_off)); -#else - // Need to marshal 64-bit value from misaligned Lesp loads - __ stf(FloatRegisterImpl::S, r_1->as_FloatRegister(), base, next_arg_slot(st_off)); - __ stf(FloatRegisterImpl::S, r_2->as_FloatRegister(), base, arg_slot(st_off) ); -#endif } void AdapterGenerator::store_c2i_float(FloatRegister f, Register base, @@ -693,7 +532,7 @@ void AdapterGenerator::gen_c2i_adapter( const int arg_size = total_args_passed * Interpreter::stackElementSize; const int varargs_area = (frame::varargs_offset - frame::register_save_words)*wordSize; - const int extraspace = round_to(arg_size + varargs_area, 2*wordSize); + const int extraspace = align_up(arg_size + varargs_area, 2*wordSize); const int bias = STACK_BIAS; const int interp_arg_offset = frame::varargs_offset*wordSize + @@ -915,9 +754,9 @@ void AdapterGenerator::gen_i2c_adapter(int total_args_passed, // in registers, we will commonly have no stack args. if (comp_args_on_stack > 0) { // Convert VMReg stack slots to words. - int comp_words_on_stack = round_to(comp_args_on_stack*VMRegImpl::stack_slot_size, wordSize)>>LogBytesPerWord; + int comp_words_on_stack = align_up(comp_args_on_stack*VMRegImpl::stack_slot_size, wordSize)>>LogBytesPerWord; // Round up to miminum stack alignment, in wordSize - comp_words_on_stack = round_to(comp_words_on_stack, 2); + comp_words_on_stack = align_up(comp_words_on_stack, 2); // Now compute the distance from Lesp to SP. This calculation does not // include the space for total_args_passed because Lesp has not yet popped // the arguments. @@ -957,22 +796,17 @@ void AdapterGenerator::gen_i2c_adapter(int total_args_passed, if (!r_2->is_valid()) { __ ld(Gargs, arg_slot(ld_off), r); } else { -#ifdef _LP64 // In V9, longs are given 2 64-bit slots in the interpreter, but the // data is passed in only 1 slot. RegisterOrConstant slot = (sig_bt[i] == T_LONG) ? next_arg_slot(ld_off) : arg_slot(ld_off); __ ldx(Gargs, slot, r); -#else - fatal("longs should be on stack"); -#endif } } else { assert(r_1->is_FloatRegister(), ""); if (!r_2->is_valid()) { __ ldf(FloatRegisterImpl::S, Gargs, arg_slot(ld_off), r_1->as_FloatRegister()); } else { -#ifdef _LP64 // In V9, doubles are given 2 64-bit slots in the interpreter, but the // data is passed in only 1 slot. This code also handles longs that // are passed on the stack, but need a stack-to-stack move through a @@ -980,11 +814,6 @@ void AdapterGenerator::gen_i2c_adapter(int total_args_passed, RegisterOrConstant slot = (sig_bt[i] == T_LONG || sig_bt[i] == T_DOUBLE) ? next_arg_slot(ld_off) : arg_slot(ld_off); __ ldf(FloatRegisterImpl::D, Gargs, slot, r_1->as_FloatRegister()); -#else - // Need to marshal 64-bit value from misaligned Lesp loads - __ ldf(FloatRegisterImpl::S, Gargs, next_arg_slot(ld_off), r_1->as_FloatRegister()); - __ ldf(FloatRegisterImpl::S, Gargs, arg_slot(ld_off), r_2->as_FloatRegister()); -#endif } } // Was the argument really intended to be on the stack, but was loaded @@ -1157,7 +986,6 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt, // See int_stk_helper for a further discussion. int max_stack_slots = (frame::varargs_offset * VMRegImpl::slots_per_word) - SharedRuntime::out_preserve_stack_slots(); -#ifdef _LP64 // V9 convention: All things "as-if" on double-wide stack slots. // Hoist any int/ptr/long's in the first 6 to int regs. // Hoist any flt/dbl's in the first 16 dbl regs. @@ -1241,45 +1069,7 @@ int SharedRuntime::c_calling_convention(const BasicType *sig_bt, if (off > max_stack_slots) max_stack_slots = off; } } - -#else // _LP64 - // V8 convention: first 6 things in O-regs, rest on stack. - // Alignment is willy-nilly. - for (int i = 0; i < total_args_passed; i++) { - switch (sig_bt[i]) { - case T_ADDRESS: // raw pointers, like current thread, for VM calls - case T_ARRAY: - case T_BOOLEAN: - case T_BYTE: - case T_CHAR: - case T_FLOAT: - case T_INT: - case T_OBJECT: - case T_METADATA: - case T_SHORT: - regs[i].set1(int_stk_helper(i)); - break; - case T_DOUBLE: - case T_LONG: - assert((i + 1) < total_args_passed && sig_bt[i + 1] == T_VOID, "expecting half"); - regs[i].set_pair(int_stk_helper(i + 1), int_stk_helper(i)); - break; - case T_VOID: regs[i].set_bad(); break; - default: - ShouldNotReachHere(); - } - if (regs[i].first()->is_stack()) { - int off = regs[i].first()->reg2stack(); - if (off > max_stack_slots) max_stack_slots = off; - } - if (regs[i].second()->is_stack()) { - int off = regs[i].second()->reg2stack(); - if (off > max_stack_slots) max_stack_slots = off; - } - } -#endif // _LP64 - - return round_to(max_stack_slots + 1, 2); + return align_up(max_stack_slots + 1, 2); } @@ -1406,12 +1196,7 @@ static void object_move(MacroAssembler* masm, Register rHandle = dst.first()->is_stack() ? L5 : dst.first()->as_Register(); __ add(FP, reg2offset(src.first()) + STACK_BIAS, rHandle); __ ld_ptr(rHandle, 0, L4); -#ifdef _LP64 __ movr( Assembler::rc_z, L4, G0, rHandle ); -#else - __ tst( L4 ); - __ movcc( Assembler::zero, false, Assembler::icc, G0, rHandle ); -#endif if (dst.first()->is_stack()) { __ st_ptr(rHandle, SP, reg2offset(dst.first()) + STACK_BIAS); } @@ -1432,12 +1217,7 @@ static void object_move(MacroAssembler* masm, } map->set_oop(VMRegImpl::stack2reg(oop_slot)); __ add(SP, offset + STACK_BIAS, rHandle); -#ifdef _LP64 __ movr( Assembler::rc_z, rOop, G0, rHandle ); -#else - __ tst( rOop ); - __ movcc( Assembler::zero, false, Assembler::icc, G0, rHandle ); -#endif if (dst.first()->is_stack()) { __ st_ptr(rHandle, SP, reg2offset(dst.first()) + STACK_BIAS); @@ -1853,7 +1633,7 @@ static void unpack_array_argument(MacroAssembler* masm, VMRegPair reg, BasicType } static void verify_oop_args(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, const BasicType* sig_bt, const VMRegPair* regs) { Register temp_reg = G5_method; // not part of any compiled calling seq @@ -1877,7 +1657,7 @@ static void verify_oop_args(MacroAssembler* masm, } static void gen_special_dispatch(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, const BasicType* sig_bt, const VMRegPair* regs) { verify_oop_args(masm, method, sig_bt, regs); @@ -2068,11 +1848,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ delayed()->or3(mask, markOopDesc::hash_mask & 0x3ff, mask); // Check for a valid (non-zero) hash code and get its value. -#ifdef _LP64 __ srlx(header, markOopDesc::hash_shift, hash); -#else - __ srl(header, markOopDesc::hash_shift, hash); -#endif __ andcc(hash, mask, hash); __ br(Assembler::equal, false, Assembler::pn, slowCase); __ delayed()->nop(); @@ -2214,7 +1990,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Now the space for the inbound oop handle area - int oop_handle_offset = round_to(stack_slots, 2); + int oop_handle_offset = align_up(stack_slots, 2); stack_slots += total_save_slots; // Now any space we need for handlizing a klass if static method @@ -2268,7 +2044,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Now compute actual number of stack words we need rounding to make // stack properly aligned. - stack_slots = round_to(stack_slots, 2 * VMRegImpl::slots_per_word); + stack_slots = align_up(stack_slots, 2 * VMRegImpl::slots_per_word); int stack_size = stack_slots * VMRegImpl::stack_slot_size; @@ -2408,7 +2184,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // We have all of the arguments setup at this point. We MUST NOT touch any Oregs // except O6/O7. So if we must call out we must push a new frame. We immediately // push a new frame and flush the windows. -#ifdef _LP64 intptr_t thepc = (intptr_t) __ pc(); { address here = __ pc(); @@ -2416,9 +2191,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ call(here + 8, relocInfo::none); __ delayed()->nop(); } -#else - intptr_t thepc = __ load_pc_address(O7, 0); -#endif /* _LP64 */ // We use the same pc/oopMap repeatedly when we call out oop_maps->add_gc_map(thepc - start, map); @@ -2553,13 +2325,9 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Transition from _thread_in_Java to _thread_in_native. __ set(_thread_in_native, G3_scratch); -#ifdef _LP64 AddressLiteral dest(native_func); __ relocate(relocInfo::runtime_call_type); __ jumpl_to(dest, O7, O7); -#else - __ call(native_func, relocInfo::runtime_call_type); -#endif __ delayed()->st(G3_scratch, G2_thread, JavaThread::thread_state_offset()); __ restore_thread(L7_thread_cache); // restore G2_thread @@ -2574,9 +2342,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, case T_DOUBLE: break; // Got it where we want it (unless slow-path) // In 64 bits build result is in O0, in O0, O1 in 32bit build case T_LONG: -#ifndef _LP64 - __ mov(O1, I1); -#endif // Fall thru case T_OBJECT: // Really a handle case T_ARRAY: @@ -2797,16 +2562,6 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Return -#ifndef _LP64 - if (ret_type == T_LONG) { - - // Must leave proper result in O0,O1 and G1 (c2/tiered only) - __ sllx(I0, 32, G1); // Shift bits into high G1 - __ srl (I1, 0, I1); // Zero extend O1 (harmless?) - __ or3 (I1, G1, G1); // OR 64 bits into G1 - } -#endif - __ ret(); __ delayed()->restore(); @@ -2837,7 +2592,7 @@ int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals) if (callee_locals < callee_parameters) return 0; // No adjustment for negative locals int diff = (callee_locals - callee_parameters) * Interpreter::stackElementWords; - return round_to(diff, WordsPerLong); + return align_up(diff, WordsPerLong); } // "Top of Stack" slots that may be unused by the calling convention but must @@ -2868,10 +2623,6 @@ static void gen_new_frame(MacroAssembler* masm, bool deopt) { #ifdef ASSERT // make sure that the frames are aligned properly -#ifndef _LP64 - __ btst(wordSize*2-1, SP); - __ breakpoint_trap(Assembler::notZero, Assembler::ptr_cc); -#endif #endif // Deopt needs to pass some extra live values from frame to frame @@ -2989,13 +2740,7 @@ void SharedRuntime::generate_deopt_blob() { pad += 1000; // Increase the buffer size when compiling for JVMCI } #endif -#ifdef _LP64 CodeBuffer buffer("deopt_blob", 2100+pad, 512); -#else - // Measured 8/7/03 at 1212 in 32bit debug build (no VerifyThread) - // Measured 8/7/03 at 1396 in 32bit debug build (VerifyThread) - CodeBuffer buffer("deopt_blob", 1600+pad, 512); -#endif /* _LP64 */ MacroAssembler* masm = new MacroAssembler(&buffer); FloatRegister Freturn0 = F0; Register Greturn1 = G1; @@ -3006,9 +2751,6 @@ void SharedRuntime::generate_deopt_blob() { Register G4deopt_mode = G4_scratch; int frame_size_words; Address saved_Freturn0_addr(FP, -sizeof(double) + STACK_BIAS); -#if !defined(_LP64) && defined(COMPILER2) - Address saved_Greturn1_addr(FP, -sizeof(double) -sizeof(jlong) + STACK_BIAS); -#endif Label cont; OopMapSet *oop_maps = new OopMapSet(); @@ -3220,30 +2962,13 @@ void SharedRuntime::generate_deopt_blob() { // to the interpreter entry point __ save(SP, -frame_size_words*wordSize, SP); __ stf(FloatRegisterImpl::D, Freturn0, saved_Freturn0_addr); -#if !defined(_LP64) -#if defined(COMPILER2) - // 32-bit 1-register longs return longs in G1 - __ stx(Greturn1, saved_Greturn1_addr); -#endif - __ set_last_Java_frame(SP, noreg); - __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, G4deopt_mode); -#else // LP64 uses g4 in set_last_Java_frame __ mov(G4deopt_mode, O1); __ set_last_Java_frame(SP, G0); __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::unpack_frames), G2_thread, O1); -#endif __ reset_last_Java_frame(); __ ldf(FloatRegisterImpl::D, saved_Freturn0_addr, Freturn0); -#if !defined(_LP64) && defined(COMPILER2) - // In 32 bit, C2 returns longs in G1 so restore the saved G1 into - // I0/I1 if the return value is long. - Label not_long; - __ cmp_and_br_short(O0,T_LONG, Assembler::notEqual, Assembler::pt, not_long); - __ ldd(saved_Greturn1_addr,I0); - __ bind(not_long); -#endif __ ret(); __ delayed()->restore(); @@ -3273,13 +2998,7 @@ void SharedRuntime::generate_uncommon_trap_blob() { pad += (JavaThread::stack_shadow_zone_size() / os::vm_page_size())*16 + 32; } #endif -#ifdef _LP64 CodeBuffer buffer("uncommon_trap_blob", 2700+pad, 512); -#else - // Measured 8/7/03 at 660 in 32bit debug build (no VerifyThread) - // Measured 8/7/03 at 1028 in 32bit debug build (VerifyThread) - CodeBuffer buffer("uncommon_trap_blob", 2000+pad, 512); -#endif MacroAssembler* masm = new MacroAssembler(&buffer); Register O2UnrollBlock = O2; Register O2klass_index = O2; diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 35e90204b68..07f62bac5aa 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 1998, 2017, 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 @@ -311,7 +311,6 @@ reg_class o7_regI(R_O7); // ---------------------------- // Pointer Register Classes // ---------------------------- -#ifdef _LP64 // 64-bit build means 64-bit pointers means hi/lo pairs reg_class ptr_reg( R_G1H,R_G1, R_G3H,R_G3, R_G4H,R_G4, R_G5H,R_G5, R_O0H,R_O0, R_O1H,R_O1, R_O2H,R_O2, R_O3H,R_O3, R_O4H,R_O4, R_O5H,R_O5, @@ -344,40 +343,6 @@ reg_class o1_regP(R_O1H,R_O1); reg_class o2_regP(R_O2H,R_O2); reg_class o7_regP(R_O7H,R_O7); -#else // _LP64 -// 32-bit build means 32-bit pointers means 1 register. -reg_class ptr_reg( R_G1, R_G3,R_G4,R_G5, - R_O0,R_O1,R_O2,R_O3,R_O4,R_O5, - R_L0,R_L1,R_L2,R_L3,R_L4,R_L5,R_L6,R_L7, - R_I0,R_I1,R_I2,R_I3,R_I4,R_I5); -// Lock encodings use G3 and G4 internally -reg_class lock_ptr_reg(R_G1, R_G5, - R_O0,R_O1,R_O2,R_O3,R_O4,R_O5, - R_L0,R_L1,R_L2,R_L3,R_L4,R_L5,R_L6,R_L7, - R_I0,R_I1,R_I2,R_I3,R_I4,R_I5); -// Special class for storeP instructions, which can store SP or RPC to TLS. -// It is also used for memory addressing, allowing direct TLS addressing. -reg_class sp_ptr_reg( R_G1,R_G2,R_G3,R_G4,R_G5, - R_O0,R_O1,R_O2,R_O3,R_O4,R_O5,R_SP, - R_L0,R_L1,R_L2,R_L3,R_L4,R_L5,R_L6,R_L7, - R_I0,R_I1,R_I2,R_I3,R_I4,R_I5,R_FP); -// R_L7 is the lowest-priority callee-save (i.e., NS) register -// We use it to save R_G2 across calls out of Java. -reg_class l7_regP(R_L7); - -// Other special pointer regs -reg_class g1_regP(R_G1); -reg_class g2_regP(R_G2); -reg_class g3_regP(R_G3); -reg_class g4_regP(R_G4); -reg_class g5_regP(R_G5); -reg_class i0_regP(R_I0); -reg_class o0_regP(R_O0); -reg_class o1_regP(R_O1); -reg_class o2_regP(R_O2); -reg_class o7_regP(R_O7); -#endif // _LP64 - // ---------------------------- // Long Register Classes @@ -386,12 +351,9 @@ reg_class o7_regP(R_O7); // Note: O7 is never in this class; it is sometimes used as an encoding temp. reg_class long_reg( R_G1H,R_G1, R_G3H,R_G3, R_G4H,R_G4, R_G5H,R_G5 ,R_O0H,R_O0, R_O1H,R_O1, R_O2H,R_O2, R_O3H,R_O3, R_O4H,R_O4, R_O5H,R_O5 -#ifdef _LP64 // 64-bit, longs in 1 register: use all 64-bit integer registers -// 32-bit, longs in 1 register: cannot use I's and L's. Restrict to O's and G's. ,R_L0H,R_L0, R_L1H,R_L1, R_L2H,R_L2, R_L3H,R_L3, R_L4H,R_L4, R_L5H,R_L5, R_L6H,R_L6, R_L7H,R_L7 ,R_I0H,R_I0, R_I1H,R_I1, R_I2H,R_I2, R_I3H,R_I3, R_I4H,R_I4, R_I5H,R_I5 -#endif // _LP64 ); reg_class g1_regL(R_G1H,R_G1); @@ -533,10 +495,8 @@ static Register reg_to_register_object(int register_encoding); // instructions which either zero-fill or sign-fill). bool can_branch_register( Node *bol, Node *cmp ) { if( !BranchOnRegister ) return false; -#ifdef _LP64 if( cmp->Opcode() == Op_CmpP ) return true; // No problems with pointer compares -#endif if( cmp->Opcode() == Op_CmpL ) return true; // No problems with long compares @@ -617,15 +577,11 @@ int MachCallDynamicJavaNode::ret_addr_offset() { } int MachCallRuntimeNode::ret_addr_offset() { -#ifdef _LP64 if (MacroAssembler::is_far_target(entry_point())) { return NativeFarCall::instruction_size; } else { return NativeCall::instruction_size; } -#else - return NativeCall::instruction_size; // call; delay slot -#endif } // Indicate if the safepoint node needs the polling page as an input. @@ -1024,7 +980,6 @@ void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, RelocationHolder co #ifdef ASSERT if (preserve_g2 && (VerifyCompiledCode || VerifyOops)) { -#ifdef _LP64 // Trash argument dump slots. __ set(0xb0b8ac0db0b8ac0d, G1); __ mov(G1, G5); @@ -1034,22 +989,6 @@ void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, RelocationHolder co __ stx(G1, SP, STACK_BIAS + 0x98); __ stx(G1, SP, STACK_BIAS + 0xA0); __ stx(G1, SP, STACK_BIAS + 0xA8); -#else // _LP64 - // this is also a native call, so smash the first 7 stack locations, - // and the various registers - - // Note: [SP+0x40] is sp[callee_aggregate_return_pointer_sp_offset], - // while [SP+0x44..0x58] are the argument dump slots. - __ set((intptr_t)0xbaadf00d, G1); - __ mov(G1, G5); - __ sllx(G1, 32, G1); - __ or3(G1, G5, G1); - __ mov(G1, G5); - __ stx(G1, SP, 0x40); - __ stx(G1, SP, 0x48); - __ stx(G1, SP, 0x50); - __ stw(G1, SP, 0x58); // Do not trash [SP+0x5C] which is a usable spill slot -#endif // _LP64 } #endif /*ASSERT*/ } @@ -1133,7 +1072,13 @@ void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { __ rdpc(r); - if (disp != 0) { + if (disp == 0) { + // Emitting an additional 'nop' instruction in order not to cause a code + // size adjustment in the code following the table setup (if the instruction + // immediately following after this section is a CTI). + __ nop(); + } + else { assert(r != O7, "need temporary"); __ sub(r, __ ensure_simm13_or_reg(disp, O7), r); } @@ -1262,11 +1207,7 @@ void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { if(do_polling() && ra_->C->is_method_compilation()) { st->print("SETHI #PollAddr,L0\t! Load Polling address\n\t"); -#ifdef _LP64 st->print("LDX [L0],G0\t!Poll for Safepointing\n\t"); -#else - st->print("LDUW [L0],G0\t!Poll for Safepointing\n\t"); -#endif } if(do_polling()) { @@ -1472,75 +1413,10 @@ static void mach_spill_copy_implementation_helper(const MachNode* mach, // hardware does the flop for me. Doubles are always aligned, so no problem // there. Misaligned sources only come from native-long-returns (handled // special below). -#ifndef _LP64 - if (src_first_rc == rc_int && // source is already big-endian - src_second_rc != rc_bad && // 64-bit move - ((dst_first & 1) != 0 || dst_second != dst_first + 1)) { // misaligned dst - assert((src_first & 1) == 0 && src_second == src_first + 1, "source must be aligned"); - // Do the big-endian flop. - OptoReg::Name tmp = dst_first ; dst_first = dst_second ; dst_second = tmp ; - enum RC tmp_rc = dst_first_rc; dst_first_rc = dst_second_rc; dst_second_rc = tmp_rc; - } -#endif // -------------------------------------- // Check for integer reg-reg copy if (src_first_rc == rc_int && dst_first_rc == rc_int) { -#ifndef _LP64 - if (src_first == R_O0_num && src_second == R_O1_num) { // Check for the evil O0/O1 native long-return case - // Note: The _first and _second suffixes refer to the addresses of the the 2 halves of the 64-bit value - // as stored in memory. On a big-endian machine like SPARC, this means that the _second - // operand contains the least significant word of the 64-bit value and vice versa. - OptoReg::Name tmp = OptoReg::Name(R_O7_num); - assert((dst_first & 1) == 0 && dst_second == dst_first + 1, "return a native O0/O1 long to an aligned-adjacent 64-bit reg" ); - // Shift O0 left in-place, zero-extend O1, then OR them into the dst - if ( cbuf ) { - emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[tmp], Assembler::sllx_op3, Matcher::_regEncode[src_first], 0x1020); - emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[src_second], Assembler::srl_op3, Matcher::_regEncode[src_second], 0x0000); - emit3 (*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler:: or_op3, Matcher::_regEncode[tmp], 0, Matcher::_regEncode[src_second]); -#ifndef PRODUCT - } else { - print_helper(st, "SLLX R_%s,32,R_%s\t! Move O0-first to O7-high\n\t", OptoReg::regname(src_first), OptoReg::regname(tmp)); - print_helper(st, "SRL R_%s, 0,R_%s\t! Zero-extend O1\n\t", OptoReg::regname(src_second), OptoReg::regname(src_second)); - print_helper(st, "OR R_%s,R_%s,R_%s\t! spill",OptoReg::regname(tmp), OptoReg::regname(src_second), OptoReg::regname(dst_first)); -#endif - } - return; - } else if (dst_first == R_I0_num && dst_second == R_I1_num) { - // returning a long value in I0/I1 - // a SpillCopy must be able to target a return instruction's reg_class - // Note: The _first and _second suffixes refer to the addresses of the the 2 halves of the 64-bit value - // as stored in memory. On a big-endian machine like SPARC, this means that the _second - // operand contains the least significant word of the 64-bit value and vice versa. - OptoReg::Name tdest = dst_first; - - if (src_first == dst_first) { - tdest = OptoReg::Name(R_O7_num); - } - - if (cbuf) { - assert((src_first & 1) == 0 && (src_first + 1) == src_second, "return value was in an aligned-adjacent 64-bit reg"); - // Shift value in upper 32-bits of src to lower 32-bits of I0; move lower 32-bits to I1 - // ShrL_reg_imm6 - emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[tdest], Assembler::srlx_op3, Matcher::_regEncode[src_second], 32 | 0x1000); - // ShrR_reg_imm6 src, 0, dst - emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srl_op3, Matcher::_regEncode[src_first], 0x0000); - if (tdest != dst_first) { - emit3 (*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler::or_op3, 0/*G0*/, 0/*op2*/, Matcher::_regEncode[tdest]); - } - } -#ifndef PRODUCT - else { - print_helper(st, "SRLX R_%s,32,R_%s\t! Extract MSW\n\t",OptoReg::regname(src_second),OptoReg::regname(tdest)); - print_helper(st, "SRL R_%s, 0,R_%s\t! Extract LSW\n\t",OptoReg::regname(src_first),OptoReg::regname(dst_second)); - if (tdest != dst_first) { - print_helper(st, "MOV R_%s,R_%s\t! spill\n\t", OptoReg::regname(tdest), OptoReg::regname(dst_first)); - } - } -#endif // PRODUCT - return size+8; - } -#endif // !_LP64 // Else normal reg-reg copy assert(src_second != dst_first, "smashed second before evacuating it"); impl_mov_helper(cbuf, src_first, dst_first, Assembler::or_op3, 0, "MOV ", st); @@ -1614,58 +1490,6 @@ static void mach_spill_copy_implementation_helper(const MachNode* mach, } assert(src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad"); -#ifndef _LP64 - // In the LP64 build, all registers can be moved as aligned/adjacent - // pairs, so there's never any need to move the high bits separately. - // The 32-bit builds have to deal with the 32-bit ABI which can force - // all sorts of silly alignment problems. - - // Check for integer reg-reg copy. Hi bits are stuck up in the top - // 32-bits of a 64-bit register, but are needed in low bits of another - // register (else it's a hi-bits-to-hi-bits copy which should have - // happened already as part of a 64-bit move) - if (src_second_rc == rc_int && dst_second_rc == rc_int) { - assert((src_second & 1) == 1, "its the evil O0/O1 native return case"); - assert((dst_second & 1) == 0, "should have moved with 1 64-bit move"); - // Shift src_second down to dst_second's low bits. - if (cbuf) { - emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020); -#ifndef PRODUCT - } else { - print_helper(st, "SRLX R_%s,32,R_%s\t! spill: Move high bits down low", OptoReg::regname(src_second - 1), OptoReg::regname(dst_second)); -#endif - } - return; - } - - // Check for high word integer store. Must down-shift the hi bits - // into a temp register, then fall into the case of storing int bits. - if (src_second_rc == rc_int && dst_second_rc == rc_stack && (src_second & 1) == 1) { - // Shift src_second down to dst_second's low bits. - if (cbuf) { - emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[R_O7_num], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020); -#ifndef PRODUCT - } else { - print_helper(st, "SRLX R_%s,32,R_%s\t! spill: Move high bits down low", OptoReg::regname(src_second-1), OptoReg::regname(R_O7_num)); -#endif - } - src_second = OptoReg::Name(R_O7_num); // Not R_O7H_num! - } - - // Check for high word integer load - if (dst_second_rc == rc_int && src_second_rc == rc_stack) - return impl_helper(this, cbuf, ra_, true, ra_->reg2offset(src_second), dst_second, Assembler::lduw_op3, "LDUW", size, st); - - // Check for high word integer store - if (src_second_rc == rc_int && dst_second_rc == rc_stack) - return impl_helper(this, cbuf, ra_, false, ra_->reg2offset(dst_second), src_second, Assembler::stw_op3, "STW ", size, st); - - // Check for high word float store - if (src_second_rc == rc_float && dst_second_rc == rc_stack) - return impl_helper(this, cbuf, ra_, false, ra_->reg2offset(dst_second), src_second, Assembler::stf_op3, "STF ", size, st); - -#endif // !_LP64 - Unimplemented(); } @@ -1743,7 +1567,6 @@ uint BoxLockNode::size(PhaseRegAlloc *ra_) const { #ifndef PRODUCT void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { st->print_cr("\nUEP:"); -#ifdef _LP64 if (UseCompressedClassPointers) { assert(Universe::heap() != NULL, "java heap should be initialized"); st->print_cr("\tLDUW [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check - compressed klass"); @@ -1762,11 +1585,6 @@ void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { } st->print_cr("\tCMP R_G5,R_G3" ); st->print ("\tTne xcc,R_G0+ST_RESERVED_FOR_USER_0+2"); -#else // _LP64 - st->print_cr("\tLDUW [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check"); - st->print_cr("\tCMP R_G5,R_G3" ); - st->print ("\tTne icc,R_G0+ST_RESERVED_FOR_USER_0+2"); -#endif // _LP64 } #endif @@ -1874,9 +1692,7 @@ const bool Matcher::match_rule_supported(int opcode) { if (!UsePopCountInstruction) return false; case Op_CompareAndSwapL: -#ifdef _LP64 case Op_CompareAndSwapP: -#endif if (!VM_Version::supports_cx8()) return false; break; @@ -1919,12 +1735,12 @@ const int Matcher::vector_width_in_bytes(BasicType bt) { } // Vector ideal reg -const int Matcher::vector_ideal_reg(int size) { +const uint Matcher::vector_ideal_reg(int size) { assert(MaxVectorSize == 8, ""); return Op_RegD; } -const int Matcher::vector_shift_count_ideal_reg(int size) { +const uint Matcher::vector_shift_count_ideal_reg(int size) { fatal("vector shift is not supported"); return Node::NotAMachineReg; } @@ -1950,10 +1766,8 @@ const bool Matcher::pass_original_key_for_aes() { return true; } -// USII supports fxtof through the whole range of number, USIII doesn't -const bool Matcher::convL2FSupported(void) { - return VM_Version::has_fast_fxtof(); -} +// NOTE: All currently supported SPARC HW provides fast conversion. +const bool Matcher::convL2FSupported(void) { return true; } // Is this branch offset short enough that a short branch can be used? // @@ -1979,9 +1793,9 @@ const bool Matcher::init_array_count_is_in_bytes = true; // No additional cost for CMOVL. const int Matcher::long_cmove_cost() { return 0; } -// CMOVF/CMOVD are expensive on T4 and on SPARC64. +// CMOVF/CMOVD are expensive on e.g., T4 and SPARC64. const int Matcher::float_cmove_cost() { - return (VM_Version::is_T4() || VM_Version::is_sparc64()) ? ConditionalMoveLimit : 0; + return VM_Version::has_fast_cmove() ? 0 : ConditionalMoveLimit; } // Does the CPU require late expand (see block.cpp for description of late expand)? @@ -1992,13 +1806,11 @@ const bool Matcher::require_postalloc_expand = false; const bool Matcher::need_masked_shift_count = false; bool Matcher::narrow_oop_use_complex_address() { - NOT_LP64(ShouldNotCallThis()); assert(UseCompressedOops, "only for compressed oops code"); return false; } bool Matcher::narrow_klass_use_complex_address() { - NOT_LP64(ShouldNotCallThis()); assert(UseCompressedClassPointers, "only for compressed klass code"); return false; } @@ -2027,11 +1839,7 @@ const bool Matcher::rematerialize_float_constants = false; // needed. Else we split the double into 2 integer pieces and move it // piece-by-piece. Only happens when passing doubles into C code as the // Java calling convention forces doubles to be aligned. -#ifdef _LP64 const bool Matcher::misaligned_doubles_ok = true; -#else -const bool Matcher::misaligned_doubles_ok = false; -#endif // No-op on SPARC. void Matcher::pd_implicit_null_fixup(MachNode *node, uint idx) { @@ -2050,11 +1858,7 @@ bool Matcher::float_in_double() { return false; } // The relevant question is how the int is callee-saved. In _LP64 // the whole long is written but de-opt'ing will have to extract // the relevant 32 bits, in not-_LP64 only the low 32 bits is written. -#ifdef _LP64 const bool Matcher::int_in_long = true; -#else -const bool Matcher::int_in_long = false; -#endif // Return whether or not this register is ever used as an argument. This // function is used on startup to build the trampoline stubs in generateOptoStub. @@ -2068,7 +1872,6 @@ bool Matcher::can_be_java_arg( int reg ) { reg == R_I3_num || reg == R_I4_num || reg == R_I5_num ) return true; -#ifdef _LP64 // 64-bit builds can pass 64-bit pointers and longs in // the high I registers if( reg == R_I0H_num || @@ -2082,14 +1885,6 @@ bool Matcher::can_be_java_arg( int reg ) { return true; } -#else - // 32-bit builds with longs-in-one-entry pass longs in G1 & G4. - // Longs cannot be passed in O regs, because O regs become I regs - // after a 'save' and I regs get their high bits chopped off on - // interrupt. - if( reg == R_G1H_num || reg == R_G1_num ) return true; - if( reg == R_G4H_num || reg == R_G4_num ) return true; -#endif // A few float args in registers if( reg >= R_F0_num && reg <= R_F7_num ) return true; @@ -2152,19 +1947,11 @@ void Compile::reshape_address(AddPNode* addp) { // The intptr_t operand types, defined by textual substitution. // (Cf. opto/type.hpp. This lets us avoid many, many other ifdefs.) -#ifdef _LP64 #define immX immL #define immX13 immL13 #define immX13m7 immL13m7 #define iRegX iRegL #define g1RegX g1RegL -#else -#define immX immI -#define immX13 immI13 -#define immX13m7 immI13m7 -#define iRegX iRegI -#define g1RegX g1RegI -#endif //----------ENCODING BLOCK----------------------------------------------------- // This block specifies the encoding classes used by the compiler to output @@ -2326,7 +2113,6 @@ encode %{ emit3_simm13( cbuf, Assembler::arith_op, R_O1_enc, Assembler::add_op3, R_O7_enc, frame::pc_return_offset ); %} -#ifdef _LP64 /* %%% merge with enc_to_bool */ enc_class enc_convP2B( iRegI dst, iRegP src ) %{ MacroAssembler _masm(&cbuf); @@ -2335,7 +2121,6 @@ encode %{ Register dst_reg = reg_to_register_object($dst$$reg); __ movr(Assembler::rc_nz, src_reg, 1, dst_reg); %} -#endif enc_class enc_cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, iRegI tmp ) %{ // (Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q))) @@ -2626,16 +2411,6 @@ encode %{ // to G1 so the register allocator will not have to deal with the misaligned register // pair. enc_class adjust_long_from_native_call %{ -#ifndef _LP64 - if (returns_long()) { - // sllx O0,32,O0 - emit3_simm13( cbuf, Assembler::arith_op, R_O0_enc, Assembler::sllx_op3, R_O0_enc, 0x1020 ); - // srl O1,0,O1 - emit3_simm13( cbuf, Assembler::arith_op, R_O1_enc, Assembler::srl_op3, R_O1_enc, 0x0000 ); - // or O0,O1,G1 - emit3 ( cbuf, Assembler::arith_op, R_G1_enc, Assembler:: or_op3, R_O0_enc, 0, R_O1_enc ); - } -#endif %} enc_class Java_To_Runtime (method meth) %{ // CALL Java_To_Runtime @@ -2852,6 +2627,33 @@ enc_class fsqrtd (dflt_reg dst, dflt_reg src) %{ __ fsqrt(FloatRegisterImpl::D, Fsrc, Fdst); %} + + +enc_class fmadds (sflt_reg dst, sflt_reg a, sflt_reg b, sflt_reg c) %{ + MacroAssembler _masm(&cbuf); + + FloatRegister Frd = reg_to_SingleFloatRegister_object($dst$$reg); + FloatRegister Fra = reg_to_SingleFloatRegister_object($a$$reg); + FloatRegister Frb = reg_to_SingleFloatRegister_object($b$$reg); + FloatRegister Frc = reg_to_SingleFloatRegister_object($c$$reg); + + __ fmadd(FloatRegisterImpl::S, Fra, Frb, Frc, Frd); +%} + +enc_class fmaddd (dflt_reg dst, dflt_reg a, dflt_reg b, dflt_reg c) %{ + MacroAssembler _masm(&cbuf); + + FloatRegister Frd = reg_to_DoubleFloatRegister_object($dst$$reg); + FloatRegister Fra = reg_to_DoubleFloatRegister_object($a$$reg); + FloatRegister Frb = reg_to_DoubleFloatRegister_object($b$$reg); + FloatRegister Frc = reg_to_DoubleFloatRegister_object($c$$reg); + + __ fmadd(FloatRegisterImpl::D, Fra, Frb, Frc, Frd); +%} + + + + enc_class fmovs (dflt_reg dst, dflt_reg src) %{ MacroAssembler _masm(&cbuf); @@ -3102,11 +2904,7 @@ frame %{ cisc_spilling_operand_name(indOffset); // Number of stack slots consumed by a Monitor enter -#ifdef _LP64 sync_stack_slots(2); -#else - sync_stack_slots(1); -#endif // Compiled code's Frame Pointer frame_pointer(R_SP); @@ -3124,13 +2922,8 @@ frame %{ // Number of outgoing stack slots killed above the out_preserve_stack_slots // for calls to C. Supports the var-args backing area for register parms. // ADLC doesn't support parsing expressions, so I folded the math by hand. -#ifdef _LP64 // (callee_register_argument_save_area_words (6) + callee_aggregate_return_pointer_words (0)) * 2-stack-slots-per-word varargs_C_out_slots_killed(12); -#else - // (callee_register_argument_save_area_words (6) + callee_aggregate_return_pointer_words (1)) * 1-stack-slots-per-word - varargs_C_out_slots_killed( 7); -#endif // The after-PROLOG location of the return address. Location of // return address specifies a type (REG or STACK) and a number @@ -3161,17 +2954,10 @@ frame %{ // opcodes. This simplifies the register allocator. c_return_value %{ assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" ); -#ifdef _LP64 static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num }; static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num}; static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num }; static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num}; -#else // !_LP64 - static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num }; - static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num }; -#endif return OptoRegPair( (is_outgoing?hi_out:hi_in)[ideal_reg], (is_outgoing?lo_out:lo_in)[ideal_reg] ); %} @@ -3179,17 +2965,10 @@ frame %{ // Location of compiled Java return values. Same as C return_value %{ assert( ideal_reg >= Op_RegI && ideal_reg <= Op_RegL, "only return normal values" ); -#ifdef _LP64 static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_O0_num }; static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_O0H_num, OptoReg::Bad, R_F1_num, R_O0H_num}; static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_I0_num }; static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_I0H_num, OptoReg::Bad, R_F1_num, R_I0H_num}; -#else // !_LP64 - static int lo_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_O0_num, R_O0_num, R_O0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_out[Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num}; - static int lo_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, R_I0_num, R_I0_num, R_I0_num, R_F0_num, R_F0_num, R_G1_num }; - static int hi_in [Op_RegL+1] = { OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, OptoReg::Bad, R_F1_num, R_G1H_num}; -#endif return OptoRegPair( (is_outgoing?hi_out:hi_in)[ideal_reg], (is_outgoing?lo_out:lo_in)[ideal_reg] ); %} @@ -3454,10 +3233,9 @@ operand immP() %{ interface(CONST_INTER); %} -#ifdef _LP64 // Pointer Immediate: 64-bit operand immP_set() %{ - predicate(!VM_Version::is_niagara_plus()); + predicate(!VM_Version::has_fast_ld()); match(ConP); op_cost(5); @@ -3469,7 +3247,7 @@ operand immP_set() %{ // Pointer Immediate: 64-bit // From Niagara2 processors on a load should be better than materializing. operand immP_load() %{ - predicate(VM_Version::is_niagara_plus() && (n->bottom_type()->isa_oop_ptr() || (MacroAssembler::insts_for_set(n->get_ptr()) > 3))); + predicate(VM_Version::has_fast_ld() && (n->bottom_type()->isa_oop_ptr() || (MacroAssembler::insts_for_set(n->get_ptr()) > 3))); match(ConP); op_cost(5); @@ -3480,7 +3258,7 @@ operand immP_load() %{ // Pointer Immediate: 64-bit operand immP_no_oop_cheap() %{ - predicate(VM_Version::is_niagara_plus() && !n->bottom_type()->isa_oop_ptr() && (MacroAssembler::insts_for_set(n->get_ptr()) <= 3)); + predicate(VM_Version::has_fast_ld() && !n->bottom_type()->isa_oop_ptr() && (MacroAssembler::insts_for_set(n->get_ptr()) <= 3)); match(ConP); op_cost(5); @@ -3488,7 +3266,6 @@ operand immP_no_oop_cheap() %{ format %{ %} interface(CONST_INTER); %} -#endif operand immP13() %{ predicate((-4096 < n->get_ptr()) && (n->get_ptr() <= 4095)); @@ -3605,7 +3382,7 @@ operand immL_32bits() %{ // Long Immediate: cheap (materialize in <= 3 instructions) operand immL_cheap() %{ - predicate(!VM_Version::is_niagara_plus() || MacroAssembler::insts_for_set64(n->get_long()) <= 3); + predicate(!VM_Version::has_fast_ld() || MacroAssembler::insts_for_set64(n->get_long()) <= 3); match(ConL); op_cost(0); @@ -3615,7 +3392,7 @@ operand immL_cheap() %{ // Long Immediate: expensive (materialize in > 3 instructions) operand immL_expensive() %{ - predicate(VM_Version::is_niagara_plus() && MacroAssembler::insts_for_set64(n->get_long()) > 3); + predicate(VM_Version::has_fast_ld() && MacroAssembler::insts_for_set64(n->get_long()) > 3); match(ConL); op_cost(0); @@ -3929,11 +3706,7 @@ operand flagsRegP() %{ constraint(ALLOC_IN_RC(int_flags)); match(RegFlags); -#ifdef _LP64 format %{ "xcc_P" %} -#else - format %{ "icc_P" %} -#endif interface(REG_INTER); %} @@ -4519,7 +4292,6 @@ pipe_class ialu_reg_flags( iRegI op2_out, iRegI op2_in, iRegI op1, flagsReg cr ) MS : R(2); %} -#ifdef _LP64 pipe_class ialu_clr_and_mover( iRegI dst, iRegP src ) %{ instruction_count(1); multiple_bundles; dst : C(write)+1; @@ -4528,7 +4300,6 @@ pipe_class ialu_clr_and_mover( iRegI dst, iRegP src ) %{ BR : E(2); MS : E(2); %} -#endif // Integer ALU reg operation pipe_class ialu_move_reg_L_to_I(iRegI dst, iRegL src) %{ @@ -4633,13 +4404,8 @@ pipe_class loadConP( iRegP dst, immP src ) %{ // Polling Address pipe_class loadConP_poll( iRegP dst, immP_poll src ) %{ -#ifdef _LP64 instruction_count(0); multiple_bundles; fixed_latency(6); -#else - dst : E(write); - IALU : R; -#endif %} // Long Constant small @@ -4820,6 +4586,26 @@ pipe_class fdivD_reg_reg(regD dst, regD src1, regD src2) %{ FDIV : C(17); %} +// Fused floating-point multiply-add float. +pipe_class fmaF_regx4(regF dst, regF src1, regF src2, regF src3) %{ + single_instruction; + dst : X(write); + src1 : E(read); + src2 : E(read); + src3 : E(read); + FM : R; +%} + +// Fused gloating-point multiply-add double. +pipe_class fmaD_regx4(regD dst, regD src1, regD src2, regD src3) %{ + single_instruction; + dst : X(write); + src1 : E(read); + src2 : E(read); + src3 : E(read); + FM : R; +%} + // Floating Point Move/Negate/Abs Float pipe_class faddF_reg(regF dst, regF src) %{ single_instruction; @@ -5380,7 +5166,6 @@ instruct regL_to_stkL(stackSlotL dst, iRegL src) %{ ins_pipe(istore_mem_reg); %} -#ifdef _LP64 // Load pointer from stack slot, 64-bit encoding instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{ match(Set dst src); @@ -5400,27 +5185,6 @@ instruct regP_to_stkP(stackSlotP dst, iRegP src) %{ ins_encode(simple_form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_reg); %} -#else // _LP64 -// Load pointer from stack slot, 32-bit encoding -instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{ - match(Set dst src); - ins_cost(MEMORY_REF_COST); - format %{ "LDUW $src,$dst\t!ptr" %} - opcode(Assembler::lduw_op3, Assembler::ldst_op); - ins_encode(simple_form3_mem_reg( src, dst ) ); - ins_pipe(iload_mem); -%} - -// Store pointer to stack slot -instruct regP_to_stkP(stackSlotP dst, iRegP src) %{ - match(Set dst src); - ins_cost(MEMORY_REF_COST); - format %{ "STW $src,$dst\t!ptr" %} - opcode(Assembler::stw_op3, Assembler::ldst_op); - ins_encode(simple_form3_mem_reg( dst, src ) ); - ins_pipe(istore_mem_reg); -%} -#endif // _LP64 //------------Special Nop instructions for bundling - no match rules----------- // Nop using the A0 functional unit @@ -5877,17 +5641,10 @@ instruct loadP(iRegP dst, memory mem) %{ ins_cost(MEMORY_REF_COST); size(4); -#ifndef _LP64 - format %{ "LDUW $mem,$dst\t! ptr" %} - ins_encode %{ - __ lduw($mem$$Address, $dst$$Register); - %} -#else format %{ "LDX $mem,$dst\t! ptr" %} ins_encode %{ __ ldx($mem$$Address, $dst$$Register); %} -#endif ins_pipe(iload_mem); %} @@ -5910,17 +5667,10 @@ instruct loadKlass(iRegP dst, memory mem) %{ ins_cost(MEMORY_REF_COST); size(4); -#ifndef _LP64 - format %{ "LDUW $mem,$dst\t! klass ptr" %} - ins_encode %{ - __ lduw($mem$$Address, $dst$$Register); - %} -#else format %{ "LDX $mem,$dst\t! klass ptr" %} ins_encode %{ __ ldx($mem$$Address, $dst$$Register); %} -#endif ins_pipe(iload_mem); %} @@ -5988,26 +5738,6 @@ instruct loadConI13( iRegI dst, immI13 src ) %{ ins_pipe(ialu_imm); %} -#ifndef _LP64 -instruct loadConP(iRegP dst, immP con) %{ - match(Set dst con); - ins_cost(DEFAULT_COST * 3/2); - format %{ "SET $con,$dst\t!ptr" %} - ins_encode %{ - relocInfo::relocType constant_reloc = _opnds[1]->constant_reloc(); - intptr_t val = $con$$constant; - if (constant_reloc == relocInfo::oop_type) { - __ set_oop_constant((jobject) val, $dst$$Register); - } else if (constant_reloc == relocInfo::metadata_type) { - __ set_metadata_constant((Metadata*)val, $dst$$Register); - } else { // non-oop pointers, e.g. card mark base, heap top - assert(constant_reloc == relocInfo::none, "unexpected reloc type"); - __ set(val, $dst$$Register); - } - %} - ins_pipe(loadConP); -%} -#else instruct loadConP_set(iRegP dst, immP_set con) %{ match(Set dst con); ins_cost(DEFAULT_COST * 3/2); @@ -6051,7 +5781,6 @@ instruct loadConP_no_oop_cheap(iRegP dst, immP_no_oop_cheap con) %{ %} ins_pipe(loadConP); %} -#endif // _LP64 instruct loadConP0(iRegP dst, immP0 src) %{ match(Set dst src); @@ -6205,19 +5934,6 @@ instruct prefetchAlloc_bis( iRegP dst ) %{ %} // Next code is used for finding next cache line address to prefetch. -#ifndef _LP64 -instruct cacheLineAdr( iRegP dst, iRegP src, immI13 mask ) %{ - match(Set dst (CastX2P (AndI (CastP2X src) mask))); - ins_cost(DEFAULT_COST); - size(4); - - format %{ "AND $src,$mask,$dst\t! next cache line address" %} - ins_encode %{ - __ and3($src$$Register, $mask$$constant, $dst$$Register); - %} - ins_pipe(ialu_reg_imm); -%} -#else instruct cacheLineAdr( iRegP dst, iRegP src, immL13 mask ) %{ match(Set dst (CastX2P (AndL (CastP2X src) mask))); ins_cost(DEFAULT_COST); @@ -6229,7 +5945,6 @@ instruct cacheLineAdr( iRegP dst, iRegP src, immL13 mask ) %{ %} ins_pipe(ialu_reg_imm); %} -#endif //----------Store Instructions------------------------------------------------- // Store Byte @@ -6341,13 +6056,8 @@ instruct storeP(memory dst, sp_ptr_RegP src) %{ match(Set dst (StoreP dst src)); ins_cost(MEMORY_REF_COST); -#ifndef _LP64 - format %{ "STW $src,$dst\t! ptr" %} - opcode(Assembler::stw_op3, 0, REGP_OP); -#else format %{ "STX $src,$dst\t! ptr" %} opcode(Assembler::stx_op3, 0, REGP_OP); -#endif ins_encode( form3_mem_reg( dst, src ) ); ins_pipe(istore_mem_spORreg); %} @@ -6356,13 +6066,8 @@ instruct storeP0(memory dst, immP0 src) %{ match(Set dst (StoreP dst src)); ins_cost(MEMORY_REF_COST); -#ifndef _LP64 - format %{ "STW $src,$dst\t! ptr" %} - opcode(Assembler::stw_op3, 0, REGP_OP); -#else format %{ "STX $src,$dst\t! ptr" %} opcode(Assembler::stx_op3, 0, REGP_OP); -#endif ins_encode( form3_mem_reg( dst, R_G0 ) ); ins_pipe(istore_mem_zero); %} @@ -7113,13 +6818,8 @@ instruct loadPLocked(iRegP dst, memory mem) %{ match(Set dst (LoadPLocked mem)); ins_cost(MEMORY_REF_COST); -#ifndef _LP64 - format %{ "LDUW $mem,$dst\t! ptr" %} - opcode(Assembler::lduw_op3, 0, REGP_OP); -#else format %{ "LDX $mem,$dst\t! ptr" %} opcode(Assembler::ldx_op3, 0, REGP_OP); -#endif ins_encode( form3_mem_reg( mem, dst ) ); ins_pipe(iload_mem); %} @@ -7190,9 +6890,7 @@ instruct compareAndSwapI_bool(iRegP mem_ptr, iRegI oldval, iRegI newval, iRegI r %} instruct compareAndSwapP_bool(iRegP mem_ptr, iRegP oldval, iRegP newval, iRegI res, o7RegI tmp1, flagsReg ccr ) %{ -#ifdef _LP64 predicate(VM_Version::supports_cx8()); -#endif match(Set res (CompareAndSwapP mem_ptr (Binary oldval newval))); match(Set res (WeakCompareAndSwapP mem_ptr (Binary oldval newval))); effect( USE mem_ptr, KILL ccr, KILL tmp1); @@ -7203,13 +6901,8 @@ instruct compareAndSwapP_bool(iRegP mem_ptr, iRegP oldval, iRegP newval, iRegI r "MOV 1,$res\n\t" "MOVne xcc,R_G0,$res" %} -#ifdef _LP64 ins_encode( enc_casx(mem_ptr, oldval, newval), enc_lflags_ne_to_boolean(res) ); -#else - ins_encode( enc_casi(mem_ptr, oldval, newval), - enc_iflags_ne_to_boolean(res) ); -#endif ins_pipe( long_memory_op ); %} @@ -7287,17 +6980,6 @@ instruct xchgI( memory mem, iRegI newval) %{ ins_pipe( long_memory_op ); %} -#ifndef _LP64 -instruct xchgP( memory mem, iRegP newval) %{ - match(Set newval (GetAndSetP mem newval)); - format %{ "SWAP [$mem],$newval" %} - size(4); - ins_encode %{ - __ swap($mem$$Address, $newval$$Register); - %} - ins_pipe( long_memory_op ); -%} -#endif instruct xchgN( memory mem, iRegN newval) %{ match(Set newval (GetAndSetN mem newval)); @@ -7759,7 +7441,6 @@ instruct shrL_reg_imm6(iRegL dst, iRegL src1, immU6 src2) %{ %} // Register Shift Right Immediate with a CastP2X -#ifdef _LP64 instruct shrP_reg_imm6(iRegL dst, iRegP src1, immU6 src2) %{ match(Set dst (URShiftL (CastP2X src1) src2)); size(4); @@ -7768,16 +7449,6 @@ instruct shrP_reg_imm6(iRegL dst, iRegP src1, immU6 src2) %{ ins_encode( form3_sd_rs1_imm6_rd( src1, src2, dst ) ); ins_pipe(ialu_reg_imm); %} -#else -instruct shrP_reg_imm5(iRegI dst, iRegP src1, immU5 src2) %{ - match(Set dst (URShiftI (CastP2X src1) src2)); - size(4); - format %{ "SRL $src1,$src2,$dst\t! Cast ptr $src1 to int and shift" %} - opcode(Assembler::srl_op3, Assembler::arith_op); - ins_encode( form3_rs1_imm5_rd( src1, src2, dst ) ); - ins_pipe(ialu_reg_imm); -%} -#endif //----------Floating Point Arithmetic Instructions----------------------------- @@ -7926,6 +7597,24 @@ instruct sqrtD_reg_reg(regD dst, regD src) %{ ins_pipe(fdivD_reg_reg); %} +// Single precision fused floating-point multiply-add (d = a * b + c). +instruct fmaF_regx4(regF dst, regF a, regF b, regF c) %{ + predicate(UseFMA); + match(Set dst (FmaF c (Binary a b))); + format %{ "fmadds $a,$b,$c,$dst\t# $dst = $a * $b + $c" %} + ins_encode(fmadds(dst, a, b, c)); + ins_pipe(fmaF_regx4); +%} + +// Double precision fused floating-point multiply-add (d = a * b + c). +instruct fmaD_regx4(regD dst, regD a, regD b, regD c) %{ + predicate(UseFMA); + match(Set dst (FmaD c (Binary a b))); + format %{ "fmaddd $a,$b,$c,$dst\t# $dst = $a * $b + $c" %} + ins_encode(fmaddd(dst, a, b, c)); + ins_pipe(fmaD_regx4); +%} + //----------Logical Instructions----------------------------------------------- // And Instructions // Register And @@ -8020,21 +7709,6 @@ instruct orL_reg_imm13(iRegL dst, iRegL src1, immL13 con) %{ ins_pipe(ialu_reg_imm); %} -#ifndef _LP64 - -// Use sp_ptr_RegP to match G2 (TLS register) without spilling. -instruct orI_reg_castP2X(iRegI dst, iRegI src1, sp_ptr_RegP src2) %{ - match(Set dst (OrI src1 (CastP2X src2))); - - size(4); - format %{ "OR $src1,$src2,$dst" %} - opcode(Assembler::or_op3, Assembler::arith_op); - ins_encode( form3_rs1_rs2_rd( src1, src2, dst ) ); - ins_pipe(ialu_reg_reg); -%} - -#else - instruct orL_reg_castP2X(iRegL dst, iRegL src1, sp_ptr_RegP src2) %{ match(Set dst (OrL src1 (CastP2X src2))); @@ -8046,8 +7720,6 @@ instruct orL_reg_castP2X(iRegL dst, iRegL src1, sp_ptr_RegP src2) %{ ins_pipe(ialu_reg_reg); %} -#endif - // Xor Instructions // Register Xor instruct xorI_reg_reg(iRegI dst, iRegI src1, iRegI src2) %{ @@ -8107,17 +7779,6 @@ instruct convI2B( iRegI dst, iRegI src, flagsReg ccr ) %{ ins_pipe(ialu_reg_ialu); %} -#ifndef _LP64 -instruct convP2B( iRegI dst, iRegP src, flagsReg ccr ) %{ - match(Set dst (Conv2B src)); - effect( KILL ccr ); - ins_cost(DEFAULT_COST*2); - format %{ "CMP R_G0,$src\n\t" - "ADDX R_G0,0,$dst" %} - ins_encode( enc_to_bool( src, dst ) ); - ins_pipe(ialu_reg_ialu); -%} -#else instruct convP2B( iRegI dst, iRegP src ) %{ match(Set dst (Conv2B src)); ins_cost(DEFAULT_COST*2); @@ -8126,7 +7787,6 @@ instruct convP2B( iRegI dst, iRegP src ) %{ ins_encode( form3_g0_rs2_rd_move( src, dst ), enc_convP2B( dst, src ) ); ins_pipe(ialu_clr_and_mover); %} -#endif instruct cmpLTMask0( iRegI dst, iRegI src, immI0 zero, flagsReg ccr ) %{ match(Set dst (CmpLTMask src zero)); @@ -8669,40 +8329,6 @@ instruct mulD_regD_regD(regD dst, regD src1, regD src2) %{ ins_pipe(fmulD_reg_reg); %} -instruct convL2D_reg_slow_fxtof(regD dst, stackSlotL src) %{ - match(Set dst (ConvL2D src)); - ins_cost(DEFAULT_COST*8 + MEMORY_REF_COST*6); - - expand %{ - regD_low tmpsrc; - iRegI ix43300000; - iRegI ix41f00000; - stackSlotL lx43300000; - stackSlotL lx41f00000; - regD_low dx43300000; - regD dx41f00000; - regD tmp1; - regD_low tmp2; - regD tmp3; - regD tmp4; - - stkL_to_regD(tmpsrc, src); - - loadConI_x43300000(ix43300000); - loadConI_x41f00000(ix41f00000); - regI_to_stkLHi(lx43300000, ix43300000); - regI_to_stkLHi(lx41f00000, ix41f00000); - stkL_to_regD(dx43300000, lx43300000); - stkL_to_regD(dx41f00000, lx41f00000); - - convI2D_regDHi_regD(tmp1, tmpsrc); - regDHi_regDLo_to_regD(tmp2, dx43300000, tmpsrc); - subD_regD_regD(tmp3, tmp2, dx43300000); - mulD_regD_regD(tmp4, tmp1, dx41f00000); - addD_regD_regD(dst, tmp3, tmp4); - %} -%} - // Long to Double conversion using fast fxtof instruct convL2D_helper(regD dst, regD tmp) %{ effect(DEF dst, USE tmp); @@ -8714,7 +8340,6 @@ instruct convL2D_helper(regD dst, regD tmp) %{ %} instruct convL2D_stk_fast_fxtof(regD dst, stackSlotL src) %{ - predicate(VM_Version::has_fast_fxtof()); match(Set dst (ConvL2D src)); ins_cost(DEFAULT_COST + 3 * MEMORY_REF_COST); expand %{ @@ -8769,16 +8394,10 @@ instruct convL2F_reg(regF dst, iRegL src) %{ instruct convL2I_reg(iRegI dst, iRegL src) %{ match(Set dst (ConvL2I src)); -#ifndef _LP64 - format %{ "MOV $src.lo,$dst\t! long->int" %} - ins_encode( form3_g0_rs2_rd_move_lo2( src, dst ) ); - ins_pipe(ialu_move_reg_I_to_L); -#else size(4); format %{ "SRA $src,R_G0,$dst\t! long->int" %} ins_encode( form3_rs1_rd_signextend_lo1( src, dst ) ); ins_pipe(ialu_reg); -#endif %} // Register Shift Right Immediate @@ -9117,7 +8736,7 @@ instruct branch_short(label labl) %{ predicate(UseCBCond); effect(USE labl); - size(4); + size(4); // Assuming no NOP inserted. ins_cost(BRANCH_COST); format %{ "BA $labl\t! short branch" %} ins_encode %{ @@ -9496,7 +9115,7 @@ instruct cmpI_reg_branch_short(cmpOp cmp, iRegI op1, iRegI op2, label labl, flag predicate(UseCBCond); effect(USE labl, KILL icc); - size(4); + size(4); // Assuming no NOP inserted. ins_cost(BRANCH_COST); format %{ "CWB$cmp $op1,$op2,$labl\t! int" %} ins_encode %{ @@ -9514,7 +9133,7 @@ instruct cmpI_imm_branch_short(cmpOp cmp, iRegI op1, immI5 op2, label labl, flag predicate(UseCBCond); effect(USE labl, KILL icc); - size(4); + size(4); // Assuming no NOP inserted. ins_cost(BRANCH_COST); format %{ "CWB$cmp $op1,$op2,$labl\t! int" %} ins_encode %{ @@ -9532,7 +9151,7 @@ instruct cmpU_reg_branch_short(cmpOpU cmp, iRegI op1, iRegI op2, label labl, fla predicate(UseCBCond); effect(USE labl, KILL icc); - size(4); + size(4); // Assuming no NOP inserted. ins_cost(BRANCH_COST); format %{ "CWB$cmp $op1,$op2,$labl\t! unsigned" %} ins_encode %{ @@ -9550,7 +9169,7 @@ instruct cmpU_imm_branch_short(cmpOpU cmp, iRegI op1, immI5 op2, label labl, fla predicate(UseCBCond); effect(USE labl, KILL icc); - size(4); + size(4); // Assuming no NOP inserted. ins_cost(BRANCH_COST); format %{ "CWB$cmp $op1,$op2,$labl\t! unsigned" %} ins_encode %{ @@ -9604,7 +9223,7 @@ instruct cmpL_reg_branch_short(cmpOp cmp, iRegL op1, iRegL op2, label labl, flag predicate(UseCBCond); effect(USE labl, KILL xcc); - size(4); + size(4); // Assuming no NOP inserted. ins_cost(BRANCH_COST); format %{ "CXB$cmp $op1,$op2,$labl\t! long" %} ins_encode %{ @@ -9622,7 +9241,7 @@ instruct cmpL_imm_branch_short(cmpOp cmp, iRegL op1, immL5 op2, label labl, flag predicate(UseCBCond); effect(USE labl, KILL xcc); - size(4); + size(4); // Assuming no NOP inserted. ins_cost(BRANCH_COST); format %{ "CXB$cmp $op1,$op2,$labl\t! long" %} ins_encode %{ @@ -9641,13 +9260,9 @@ instruct cmpP_reg_branch_short(cmpOpP cmp, iRegP op1, iRegP op2, label labl, fla predicate(UseCBCond); effect(USE labl, KILL pcc); - size(4); + size(4); // Assuming no NOP inserted. ins_cost(BRANCH_COST); -#ifdef _LP64 format %{ "CXB$cmp $op1,$op2,$labl\t! ptr" %} -#else - format %{ "CWB$cmp $op1,$op2,$labl\t! ptr" %} -#endif ins_encode %{ Label* L = $labl$$label; assert(__ use_cbcond(*L), "back to back cbcond"); @@ -9663,13 +9278,9 @@ instruct cmpP_null_branch_short(cmpOpP cmp, iRegP op1, immP0 null, label labl, f predicate(UseCBCond); effect(USE labl, KILL pcc); - size(4); + size(4); // Assuming no NOP inserted. ins_cost(BRANCH_COST); -#ifdef _LP64 format %{ "CXB$cmp $op1,0,$labl\t! ptr" %} -#else - format %{ "CWB$cmp $op1,0,$labl\t! ptr" %} -#endif ins_encode %{ Label* L = $labl$$label; assert(__ use_cbcond(*L), "back to back cbcond"); @@ -9685,7 +9296,7 @@ instruct cmpN_reg_branch_short(cmpOp cmp, iRegN op1, iRegN op2, label labl, flag predicate(UseCBCond); effect(USE labl, KILL icc); - size(4); + size(4); // Assuming no NOP inserted. ins_cost(BRANCH_COST); format %{ "CWB$cmp $op1,$op2,$labl\t! compressed ptr" %} ins_encode %{ @@ -9703,7 +9314,7 @@ instruct cmpN_null_branch_short(cmpOp cmp, iRegN op1, immN0 null, label labl, fl predicate(UseCBCond); effect(USE labl, KILL icc); - size(4); + size(4); // Assuming no NOP inserted. ins_cost(BRANCH_COST); format %{ "CWB$cmp $op1,0,$labl\t! compressed ptr" %} ins_encode %{ @@ -9722,7 +9333,7 @@ instruct cmpI_reg_branchLoopEnd_short(cmpOp cmp, iRegI op1, iRegI op2, label lab predicate(UseCBCond); effect(USE labl, KILL icc); - size(4); + size(4); // Assuming no NOP inserted. ins_cost(BRANCH_COST); format %{ "CWB$cmp $op1,$op2,$labl\t! Loop end" %} ins_encode %{ @@ -9740,7 +9351,7 @@ instruct cmpI_imm_branchLoopEnd_short(cmpOp cmp, iRegI op1, immI5 op2, label lab predicate(UseCBCond); effect(USE labl, KILL icc); - size(4); + size(4); // Assuming no NOP inserted. ins_cost(BRANCH_COST); format %{ "CWB$cmp $op1,$op2,$labl\t! Loop end" %} ins_encode %{ @@ -9956,11 +9567,7 @@ instruct safePoint_poll(iRegP poll) %{ effect(USE poll); size(4); -#ifdef _LP64 format %{ "LDX [$poll],R_G0\t! Safepoint: poll for GC" %} -#else - format %{ "LDUW [$poll],R_G0\t! Safepoint: poll for GC" %} -#endif ins_encode %{ __ relocate(relocInfo::poll_type); __ ld_ptr($poll$$Register, 0, G0); @@ -10393,15 +10000,15 @@ instruct array_equalsC(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI resul instruct has_negatives(o0RegP pAryR, g3RegI iSizeR, notemp_iRegI resultR, iRegL tmp1L, iRegL tmp2L, iRegL tmp3L, iRegL tmp4L, - flagsReg ccr) + flagsReg ccr) %{ match(Set resultR (HasNegatives pAryR iSizeR)); effect(TEMP resultR, TEMP tmp1L, TEMP tmp2L, TEMP tmp3L, TEMP tmp4L, USE pAryR, USE iSizeR, KILL ccr); format %{ "has negatives byte[] $pAryR,$iSizeR -> $resultR // KILL $tmp1L,$tmp2L,$tmp3L,$tmp4L" %} ins_encode %{ - __ has_negatives($pAryR$$Register, $iSizeR$$Register, + __ has_negatives($pAryR$$Register, $iSizeR$$Register, $resultR$$Register, - $tmp1L$$Register, $tmp2L$$Register, + $tmp1L$$Register, $tmp2L$$Register, $tmp3L$$Register, $tmp4L$$Register); %} ins_pipe(long_memory_op); diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index 8babb471137..9c4713e936d 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -216,9 +216,7 @@ class StubGenerator: public StubCodeGenerator { __ ld_ptr(parameter_size.as_in().as_address(), t); // get parameter size (in words) __ sll(t, Interpreter::logStackElementSize, t); // compute number of bytes __ sub(FP, t, Gargs); // setup parameter pointer -#ifdef _LP64 __ add( Gargs, STACK_BIAS, Gargs ); // Account for LP64 stack bias -#endif __ mov(SP, O5_savedSP); @@ -271,27 +269,8 @@ class StubGenerator: public StubCodeGenerator { __ delayed()->stf(FloatRegisterImpl::D, F0, addr, G0); __ BIND(is_long); -#ifdef _LP64 __ ba(exit); __ delayed()->st_long(O0, addr, G0); // store entire long -#else -#if defined(COMPILER2) - // All return values are where we want them, except for Longs. C2 returns - // longs in G1 in the 32-bit build whereas the interpreter wants them in O0/O1. - // Since the interpreter will return longs in G1 and O0/O1 in the 32bit - // build we simply always use G1. - // Note: I tried to make c2 return longs in O0/O1 and G1 so we wouldn't have to - // do this here. Unfortunately if we did a rethrow we'd see an machepilog node - // first which would move g1 -> O0/O1 and destroy the exception we were throwing. - - __ ba(exit); - __ delayed()->stx(G1, addr, G0); // store entire long -#else - __ st(O1, addr, BytesPerInt); - __ ba(exit); - __ delayed()->st(O0, addr, G0); -#endif /* COMPILER2 */ -#endif /* _LP64 */ } return start; } @@ -746,22 +725,10 @@ class StubGenerator: public StubCodeGenerator { address start = __ pc(); Label miss; -#if defined(COMPILER2) && !defined(_LP64) - // Do not use a 'save' because it blows the 64-bit O registers. - __ add(SP,-4*wordSize,SP); // Make space for 4 temps (stack must be 2 words aligned) - __ st_ptr(L0,SP,(frame::register_save_words+0)*wordSize); - __ st_ptr(L1,SP,(frame::register_save_words+1)*wordSize); - __ st_ptr(L2,SP,(frame::register_save_words+2)*wordSize); - __ st_ptr(L3,SP,(frame::register_save_words+3)*wordSize); - Register Rret = O0; - Register Rsub = O1; - Register Rsuper = O2; -#else __ save_frame(0); Register Rret = I0; Register Rsub = I1; Register Rsuper = I2; -#endif Register L0_ary_len = L0; Register L1_ary_ptr = L1; @@ -775,32 +742,14 @@ class StubGenerator: public StubCodeGenerator { // Match falls through here. __ addcc(G0,0,Rret); // set Z flags, Z result -#if defined(COMPILER2) && !defined(_LP64) - __ ld_ptr(SP,(frame::register_save_words+0)*wordSize,L0); - __ ld_ptr(SP,(frame::register_save_words+1)*wordSize,L1); - __ ld_ptr(SP,(frame::register_save_words+2)*wordSize,L2); - __ ld_ptr(SP,(frame::register_save_words+3)*wordSize,L3); - __ retl(); // Result in Rret is zero; flags set to Z - __ delayed()->add(SP,4*wordSize,SP); -#else __ ret(); // Result in Rret is zero; flags set to Z __ delayed()->restore(); -#endif __ BIND(miss); __ addcc(G0,1,Rret); // set NZ flags, NZ result -#if defined(COMPILER2) && !defined(_LP64) - __ ld_ptr(SP,(frame::register_save_words+0)*wordSize,L0); - __ ld_ptr(SP,(frame::register_save_words+1)*wordSize,L1); - __ ld_ptr(SP,(frame::register_save_words+2)*wordSize,L2); - __ ld_ptr(SP,(frame::register_save_words+3)*wordSize,L3); - __ retl(); // Result in Rret is != 0; flags set to NZ - __ delayed()->add(SP,4*wordSize,SP); -#else __ ret(); // Result in Rret is != 0; flags set to NZ __ delayed()->restore(); -#endif return start; } @@ -828,11 +777,11 @@ class StubGenerator: public StubCodeGenerator { // Rtmp - scratch // void assert_clean_int(Register Rint, Register Rtmp) { -#if defined(ASSERT) && defined(_LP64) + #if defined(ASSERT) __ signx(Rint, Rtmp); __ cmp(Rint, Rtmp); __ breakpoint_trap(Assembler::notEqual, Assembler::xcc); -#endif + #endif } // @@ -1019,10 +968,11 @@ class StubGenerator: public StubCodeGenerator { // than prefetch distance. __ set(prefetch_count, O4); __ cmp_and_brx_short(count, O4, Assembler::less, Assembler::pt, L_block_copy); - __ sub(count, prefetch_count, count); + __ sub(count, O4, count); (this->*copy_loop_func)(from, to, count, count_dec, L_block_copy_prefetch, true, true); - __ add(count, prefetch_count, count); // restore count + __ set(prefetch_count, O4); + __ add(count, O4, count); } // prefetch_count > 0 @@ -1043,11 +993,12 @@ class StubGenerator: public StubCodeGenerator { // than prefetch distance. __ set(prefetch_count, O4); __ cmp_and_brx_short(count, O4, Assembler::lessUnsigned, Assembler::pt, L_copy); - __ sub(count, prefetch_count, count); + __ sub(count, O4, count); Label L_copy_prefetch; (this->*copy_loop_func)(from, to, count, count_dec, L_copy_prefetch, true, false); - __ add(count, prefetch_count, count); // restore count + __ set(prefetch_count, O4); + __ add(count, O4, count); } // prefetch_count > 0 @@ -1269,17 +1220,6 @@ class StubGenerator: public StubCodeGenerator { // Aligned arrays have 4 bytes alignment in 32-bits VM // and 8 bytes - in 64-bits VM. So we do it only for 32-bits VM // -#ifndef _LP64 - // copy a 4-bytes word if necessary to align 'to' to 8 bytes - __ andcc(to, 7, G0); - __ br(Assembler::zero, false, Assembler::pn, L_skip_alignment); - __ delayed()->ld(from, 0, O3); - __ inc(from, 4); - __ inc(to, 4); - __ dec(count, 4); - __ st(O3, to, -4); - __ BIND(L_skip_alignment); -#endif } else { // copy bytes to align 'to' on 8 byte boundary __ andcc(to, 7, G1); // misaligned bytes @@ -1296,10 +1236,7 @@ class StubGenerator: public StubCodeGenerator { __ delayed()->inc(to); __ BIND(L_skip_alignment); } -#ifdef _LP64 - if (!aligned) -#endif - { + if (!aligned) { // Copy with shift 16 bytes per iteration if arrays do not have // the same alignment mod 8, otherwise fall through to the next // code for aligned copy. @@ -1395,15 +1332,12 @@ class StubGenerator: public StubCodeGenerator { __ delayed()->stb(O3, end_to, 0); __ BIND(L_skip_alignment); } -#ifdef _LP64 if (aligned) { // Both arrays are aligned to 8-bytes in 64-bits VM. // The 'count' is decremented in copy_16_bytes_backward_with_shift() // in unaligned case. __ dec(count, 16); - } else -#endif - { + } else { // Copy with shift 16 bytes per iteration if arrays do not have // the same alignment mod 8, otherwise jump to the next // code for aligned copy (and substracting 16 from 'count' before jump). @@ -1490,17 +1424,6 @@ class StubGenerator: public StubCodeGenerator { // Aligned arrays have 4 bytes alignment in 32-bits VM // and 8 bytes - in 64-bits VM. // -#ifndef _LP64 - // copy a 2-elements word if necessary to align 'to' to 8 bytes - __ andcc(to, 7, G0); - __ br(Assembler::zero, false, Assembler::pt, L_skip_alignment); - __ delayed()->ld(from, 0, O3); - __ inc(from, 4); - __ inc(to, 4); - __ dec(count, 2); - __ st(O3, to, -4); - __ BIND(L_skip_alignment); -#endif } else { // copy 1 element if necessary to align 'to' on an 4 bytes __ andcc(to, 3, G0); @@ -1524,10 +1447,7 @@ class StubGenerator: public StubCodeGenerator { __ sth(O4, to, -2); __ BIND(L_skip_alignment2); } -#ifdef _LP64 - if (!aligned) -#endif - { + if (!aligned) { // Copy with shift 16 bytes per iteration if arrays do not have // the same alignment mod 8, otherwise fall through to the next // code for aligned copy. @@ -1643,20 +1563,16 @@ class StubGenerator: public StubCodeGenerator { __ dec(count, 1 << (shift - 1)); __ BIND(L_skip_align2); } -#ifdef _LP64 if (!aligned) { -#endif - // align to 8 bytes, we know we are 4 byte aligned to start - __ andcc(to, 7, G0); - __ br(Assembler::zero, false, Assembler::pt, L_fill_32_bytes); - __ delayed()->nop(); - __ stw(value, to, 0); - __ inc(to, 4); - __ dec(count, 1 << shift); - __ BIND(L_fill_32_bytes); -#ifdef _LP64 + // align to 8 bytes, we know we are 4 byte aligned to start + __ andcc(to, 7, G0); + __ br(Assembler::zero, false, Assembler::pt, L_fill_32_bytes); + __ delayed()->nop(); + __ stw(value, to, 0); + __ inc(to, 4); + __ dec(count, 1 << shift); + __ BIND(L_fill_32_bytes); } -#endif if (t == T_INT) { // Zero extend value @@ -1857,15 +1773,12 @@ class StubGenerator: public StubCodeGenerator { __ sth(O4, end_to, 0); __ BIND(L_skip_alignment2); } -#ifdef _LP64 if (aligned) { // Both arrays are aligned to 8-bytes in 64-bits VM. // The 'count' is decremented in copy_16_bytes_backward_with_shift() // in unaligned case. __ dec(count, 8); - } else -#endif - { + } else { // Copy with shift 16 bytes per iteration if arrays do not have // the same alignment mod 8, otherwise jump to the next // code for aligned copy (and substracting 8 from 'count' before jump). @@ -1974,10 +1887,7 @@ class StubGenerator: public StubCodeGenerator { // Aligned arrays have 4 bytes alignment in 32-bits VM // and 8 bytes - in 64-bits VM. // -#ifdef _LP64 - if (!aligned) -#endif - { + if (!aligned) { // The next check could be put under 'ifndef' since the code in // generate_disjoint_long_copy_core() has own checks and set 'offset'. @@ -2463,16 +2373,12 @@ class StubGenerator: public StubCodeGenerator { __ mov(to, G1); __ mov(count, G5); gen_write_ref_array_pre_barrier(G1, G5, dest_uninitialized); - #ifdef _LP64 assert_clean_int(count, O3); // Make sure 'count' is clean int. if (UseCompressedOops) { generate_disjoint_int_copy_core(aligned); } else { generate_disjoint_long_copy_core(aligned); } - #else - generate_disjoint_int_copy_core(aligned); - #endif // O0 is used as temp register gen_write_ref_array_post_barrier(G1, G5, O0); @@ -2518,15 +2424,11 @@ class StubGenerator: public StubCodeGenerator { __ mov(count, G5); gen_write_ref_array_pre_barrier(G1, G5, dest_uninitialized); - #ifdef _LP64 if (UseCompressedOops) { generate_conjoint_int_copy_core(aligned); } else { generate_conjoint_long_copy_core(aligned); } - #else - generate_conjoint_int_copy_core(aligned); - #endif // O0 is used as temp register gen_write_ref_array_post_barrier(G1, G5, O0); @@ -3138,7 +3040,6 @@ class StubGenerator: public StubCodeGenerator { "arrayof_jint_disjoint_arraycopy"); StubRoutines::_arrayof_jint_arraycopy = generate_conjoint_int_copy(true, entry, &entry_jint_arraycopy, "arrayof_jint_arraycopy"); -#ifdef _LP64 // In 64 bit we need both aligned and unaligned versions of jint arraycopy. // entry_jint_arraycopy always points to the unaligned version (notice that we overwrite it). StubRoutines::_jint_disjoint_arraycopy = generate_disjoint_int_copy(false, &entry, @@ -3146,14 +3047,6 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_jint_arraycopy = generate_conjoint_int_copy(false, entry, &entry_jint_arraycopy, "jint_arraycopy"); -#else - // In 32 bit jints are always HeapWordSize aligned, so always use the aligned version - // (in fact in 32bit we always have a pre-loop part even in the aligned version, - // because it uses 64-bit loads/stores, so the aligned flag is actually ignored). - StubRoutines::_jint_disjoint_arraycopy = StubRoutines::_arrayof_jint_disjoint_arraycopy; - StubRoutines::_jint_arraycopy = StubRoutines::_arrayof_jint_arraycopy; -#endif - //*** jlong // It is always aligned @@ -3178,7 +3071,6 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_arrayof_oop_arraycopy_uninit = generate_conjoint_oop_copy(true, entry, NULL, "arrayof_oop_arraycopy_uninit", /*dest_uninitialized*/true); -#ifdef _LP64 if (UseCompressedOops) { // With compressed oops we need unaligned versions, notice that we overwrite entry_oop_arraycopy. StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_oop_copy(false, &entry, @@ -3192,9 +3084,7 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_oop_arraycopy_uninit = generate_conjoint_oop_copy(false, entry, NULL, "oop_arraycopy_uninit", /*dest_uninitialized*/true); - } else -#endif - { + } else { // oop arraycopy is always aligned on 32bit and 64bit without compressed oops StubRoutines::_oop_disjoint_arraycopy = StubRoutines::_arrayof_oop_disjoint_arraycopy; StubRoutines::_oop_arraycopy = StubRoutines::_arrayof_oop_arraycopy; @@ -5104,17 +4994,6 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::Sparc::_stop_subroutine_entry = generate_stop_subroutine(); StubRoutines::Sparc::_flush_callers_register_windows_entry = generate_flush_callers_register_windows(); -#if !defined(COMPILER2) && !defined(_LP64) - StubRoutines::_atomic_xchg_entry = generate_atomic_xchg(); - StubRoutines::_atomic_cmpxchg_entry = generate_atomic_cmpxchg(); - StubRoutines::_atomic_add_entry = generate_atomic_add(); - StubRoutines::_atomic_xchg_ptr_entry = StubRoutines::_atomic_xchg_entry; - StubRoutines::_atomic_cmpxchg_ptr_entry = StubRoutines::_atomic_cmpxchg_entry; - StubRoutines::_atomic_cmpxchg_byte_entry = ShouldNotCallThisStub(); - StubRoutines::_atomic_cmpxchg_long_entry = generate_atomic_cmpxchg_long(); - StubRoutines::_atomic_add_ptr_entry = StubRoutines::_atomic_add_entry; -#endif // COMPILER2 !=> _LP64 - // Build this early so it's available for the interpreter. StubRoutines::_throw_StackOverflowError_entry = generate_throw_exception("StackOverflowError throw_exception", @@ -5222,11 +5101,9 @@ class StubGenerator: public StubCodeGenerator { void stub_prolog(StubCodeDesc* cdesc) { # ifdef ASSERT // put extra information in the stub code, to make it more readable -#ifdef _LP64 -// Write the high part of the address -// [RGV] Check if there is a dependency on the size of this prolog + // Write the high part of the address + // [RGV] Check if there is a dependency on the size of this prolog __ emit_data((intptr_t)cdesc >> 32, relocInfo::none); -#endif __ emit_data((intptr_t)cdesc, relocInfo::none); __ emit_data(++_stub_count, relocInfo::none); # endif diff --git a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp index fd4e3ffd149..44195840bce 100644 --- a/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateInterpreterGenerator_sparc.cpp @@ -44,26 +44,18 @@ #include "runtime/synchronizer.hpp" #include "runtime/timer.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/align.hpp" #include "utilities/debug.hpp" #include "utilities/macros.hpp" -#ifndef FAST_DISPATCH -#define FAST_DISPATCH 1 -#endif -#undef FAST_DISPATCH - // Size of interpreter code. Increase if too small. Interpreter will // fail with a guarantee ("not enough space for interpreter generation"); // if too small. // Run with +PrintInterpreter to get the VM to print out the size. // Max size with JVMTI -#ifdef _LP64 - // The sethi() instruction generates lots more instructions when shell - // stack limit is unlimited, so that's why this is much bigger. +// The sethi() instruction generates lots more instructions when shell +// stack limit is unlimited, so that's why this is much bigger. int TemplateInterpreter::InterpreterCodeSize = 260 * K; -#else -int TemplateInterpreter::InterpreterCodeSize = 230 * K; -#endif // Generation of Interpreter // @@ -75,41 +67,6 @@ int TemplateInterpreter::InterpreterCodeSize = 230 * K; //---------------------------------------------------------------------------------------------------- -#ifndef _LP64 -address TemplateInterpreterGenerator::generate_slow_signature_handler() { - address entry = __ pc(); - Argument argv(0, true); - - // We are in the jni transition frame. Save the last_java_frame corresponding to the - // outer interpreter frame - // - __ set_last_Java_frame(FP, noreg); - // make sure the interpreter frame we've pushed has a valid return pc - __ mov(O7, I7); - __ mov(Lmethod, G3_scratch); - __ mov(Llocals, G4_scratch); - __ save_frame(0); - __ mov(G2_thread, L7_thread_cache); - __ add(argv.address_in_frame(), O3); - __ mov(G2_thread, O0); - __ mov(G3_scratch, O1); - __ call(CAST_FROM_FN_PTR(address, InterpreterRuntime::slow_signature_handler), relocInfo::runtime_call_type); - __ delayed()->mov(G4_scratch, O2); - __ mov(L7_thread_cache, G2_thread); - __ reset_last_Java_frame(); - - // load the register arguments (the C code packed them as varargs) - for (Argument ldarg = argv.successor(); ldarg.is_register(); ldarg = ldarg.successor()) { - __ ld_ptr(ldarg.address_in_frame(), ldarg.as_register()); - } - __ ret(); - __ delayed()-> - restore(O0, 0, Lscratch); // caller's Lscratch gets the result handler - return entry; -} - - -#else // LP64 passes floating point arguments in F1, F3, F5, etc. instead of // O0, O1, O2 etc.. // Doubles are passed in D0, D2, D4 @@ -197,16 +154,14 @@ address TemplateInterpreterGenerator::generate_slow_signature_handler() { __ delayed()->srl( G4_scratch, 2, G4_scratch ); __ bind(NextArg); - } __ bind(done); __ ret(); - __ delayed()-> - restore(O0, 0, Lscratch); // caller's Lscratch gets the result handler + __ delayed()->restore(O0, 0, Lscratch); // caller's Lscratch gets the result handler + return entry; } -#endif void TemplateInterpreterGenerator::generate_counter_overflow(Label& Lcontinue) { @@ -222,7 +177,6 @@ void TemplateInterpreterGenerator::generate_counter_overflow(Label& Lcontinue) { // returns verified_entry_point or NULL // we ignore it in any case __ ba_short(Lcontinue); - } @@ -241,7 +195,6 @@ address TemplateInterpreterGenerator::generate_abstract_entry(void) { // the call_VM checks for exception, so we should never return here. __ should_not_reach_here(); return entry; - } void TemplateInterpreterGenerator::save_native_result(void) { @@ -253,11 +206,7 @@ void TemplateInterpreterGenerator::save_native_result(void) { // save and restore any potential method result value around the unlocking operation __ stf(FloatRegisterImpl::D, F0, d_tmp); -#ifdef _LP64 __ stx(O0, l_tmp); -#else - __ std(O0, l_tmp); -#endif } void TemplateInterpreterGenerator::restore_native_result(void) { @@ -266,11 +215,7 @@ void TemplateInterpreterGenerator::restore_native_result(void) { // Restore any method result value __ ldf(FloatRegisterImpl::D, d_tmp, F0); -#ifdef _LP64 __ ldx(l_tmp, O0); -#else - __ ldd(l_tmp, O0); -#endif } address TemplateInterpreterGenerator::generate_exception_handler_common(const char* name, const char* message, bool pass_oop) { @@ -340,22 +285,6 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ profile_return_type(O0, G3_scratch, G1_scratch); } -#if !defined(_LP64) && defined(COMPILER2) - // All return values are where we want them, except for Longs. C2 returns - // longs in G1 in the 32-bit build whereas the interpreter wants them in O0/O1. - // Since the interpreter will return longs in G1 and O0/O1 in the 32bit - // build even if we are returning from interpreted we just do a little - // stupid shuffing. - // Note: I tried to make c2 return longs in O0/O1 and G1 so we wouldn't have to - // do this here. Unfortunately if we did a rethrow we'd see an machepilog node - // first which would move g1 -> O0/O1 and destroy the exception we were throwing. - - if (state == ltos) { - __ srl (G1, 0, O1); - __ srlx(G1, 32, O0); - } -#endif // !_LP64 && COMPILER2 - // The callee returns with the stack possibly adjusted by adapter transition // We remove that possible adjustment here. // All interpreter local registers are untouched. Any result is passed back @@ -374,6 +303,10 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ and3(flags, ConstantPoolCacheEntry::parameter_size_mask, parameter_size); // argument size in words __ sll(parameter_size, Interpreter::logStackElementSize, parameter_size); // each argument size in bytes __ add(Lesp, parameter_size, Lesp); // pop arguments + + __ check_and_handle_popframe(Gtemp); + __ check_and_handle_earlyret(Gtemp); + __ dispatch_next(state, step); return entry; @@ -438,9 +371,6 @@ address TemplateInterpreterGenerator::generate_result_handler_for(BasicType type case T_BYTE : __ sll(O0, 24, O0); __ sra(O0, 24, Itos_i); break; case T_SHORT : __ sll(O0, 16, O0); __ sra(O0, 16, Itos_i); break; case T_LONG : -#ifndef _LP64 - __ mov(O1, Itos_l2); // move other half of long -#endif // ifdef or no ifdef, fall through to the T_INT case case T_INT : __ mov(O0, Itos_i); break; case T_VOID : /* nothing to do */ break; case T_FLOAT : assert(F0 == Ftos_f, "fix this code" ); break; @@ -466,12 +396,6 @@ address TemplateInterpreterGenerator::generate_safept_entry_for(TosState state, } -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - address entry = __ pc(); - __ dispatch_next(state); - return entry; -} - // // Helpers for commoning out cases in the various type of method entries. // @@ -548,7 +472,6 @@ void TemplateInterpreterGenerator::generate_counter_incr(Label* overflow, Label* __ delayed()->nop(); __ bind(done); } - } // Allocate monitor and lock method (asm interpreter) @@ -664,7 +587,7 @@ void TemplateInterpreterGenerator::generate_stack_overflow_check(Register Rframe // pop parameters from the callers stack by adjusting Lesp // set O0 to Lesp // compute X = (max_locals - num_parameters) -// bump SP up by X to accomadate the extra locals +// bump SP up by X to accommodate the extra locals // compute X = max_expression_stack // + vm_local_words // + 16 words of register save area @@ -762,7 +685,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { // 1) Increase caller's SP by for the extra local space needed: // (check for overflow) // Efficient implementation of xload/xstore bytecodes requires - // that arguments and non-argument locals are in a contigously + // that arguments and non-argument locals are in a contiguously // addressable memory block => non-argument locals must be // allocated in the caller's frame. // @@ -789,7 +712,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { // (gri - 2/25/2000) - int rounded_vm_local_words = round_to( frame::interpreter_frame_vm_local_words, WordsPerLong ); + int rounded_vm_local_words = align_up((int)frame::interpreter_frame_vm_local_words, WordsPerLong ); const int extra_space = rounded_vm_local_words + // frame local scratch space @@ -856,7 +779,7 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { __ sub(Gframe_size, Glocals_size, Gframe_size); // - // bump SP to accomodate the extra locals + // bump SP to accommodate the extra locals // __ sub(SP, Glocals_size, SP); } @@ -884,22 +807,15 @@ void TemplateInterpreterGenerator::generate_fixed_frame(bool native_call) { Register mirror = LcpoolCache; __ load_mirror(mirror, Lmethod); __ st_ptr(mirror, FP, (frame::interpreter_frame_mirror_offset * wordSize) + STACK_BIAS); - __ get_constant_pool_cache( LcpoolCache ); // set LcpoolCache + __ get_constant_pool_cache(LcpoolCache); // set LcpoolCache __ sub(FP, rounded_vm_local_words * BytesPerWord, Lmonitors ); // set Lmonitors -#ifdef _LP64 - __ add( Lmonitors, STACK_BIAS, Lmonitors ); // Account for 64 bit stack bias -#endif + __ add(Lmonitors, STACK_BIAS, Lmonitors); // Account for 64 bit stack bias __ sub(Lmonitors, BytesPerWord, Lesp); // set Lesp // setup interpreter activation registers __ sub(Gargs, BytesPerWord, Llocals); // set Llocals if (ProfileInterpreter) { -#ifdef FAST_DISPATCH - // FAST_DISPATCH and ProfileInterpreter are mutually exclusive since - // they both use I2. - assert(0, "FAST_DISPATCH and +ProfileInterpreter are mutually exclusive"); -#endif // FAST_DISPATCH __ set_method_data_pointer(); } @@ -1065,7 +981,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI __ ldx( Gargs, 16, buf); __ lduw(Gargs, 24, crc); __ add(buf, arrayOopDesc::base_offset_in_bytes(T_BYTE), buf); // account for the header size - __ add(buf ,offset, buf); + __ add(buf, offset, buf); } // Call the crc32 kernel @@ -1138,8 +1054,58 @@ address TemplateInterpreterGenerator::generate_CRC32C_updateBytes_entry(Abstract return NULL; } -// Not supported -address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) { +/* Math routines only partially supported. + * + * Providing support for fma (float/double) only. + */ +address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKind kind) +{ + if (!InlineIntrinsics) return NULL; // Generate a vanilla entry + + address entry = __ pc(); + + switch (kind) { + case Interpreter::java_lang_math_fmaF: + if (UseFMA) { + // float .fma(float a, float b, float c) + const FloatRegister ra = F1; + const FloatRegister rb = F2; + const FloatRegister rc = F3; + const FloatRegister rd = F0; // Result. + + __ ldf(FloatRegisterImpl::S, Gargs, 0, rc); + __ ldf(FloatRegisterImpl::S, Gargs, 8, rb); + __ ldf(FloatRegisterImpl::S, Gargs, 16, ra); + + __ fmadd(FloatRegisterImpl::S, ra, rb, rc, rd); + __ retl(); // Result in F0 (rd). + __ delayed()->mov(O5_savedSP, SP); + + return entry; + } + break; + case Interpreter::java_lang_math_fmaD: + if (UseFMA) { + // double .fma(double a, double b, double c) + const FloatRegister ra = F2; // D1 + const FloatRegister rb = F4; // D2 + const FloatRegister rc = F6; // D3 + const FloatRegister rd = F0; // D0 Result. + + __ ldf(FloatRegisterImpl::D, Gargs, 0, rc); + __ ldf(FloatRegisterImpl::D, Gargs, 16, rb); + __ ldf(FloatRegisterImpl::D, Gargs, 32, ra); + + __ fmadd(FloatRegisterImpl::D, ra, rb, rc, rd); + __ retl(); // Result in D0 (rd). + __ delayed()->mov(O5_savedSP, SP); + + return entry; + } + break; + default: + break; + } return NULL; } @@ -1152,7 +1118,7 @@ void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) { // Doing the banging earlier fails if the caller frame is not an interpreter // frame. // (Also, the exception throwing code expects to unlock any synchronized - // method receiever, so do the banging after locking the receiver.) + // method receiver, so do the banging after locking the receiver.) // Bang each page in the shadow zone. We can't assume it's been done for // an interpreter frame with greater than a page of locals, so each page @@ -1193,8 +1159,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // rethink these assertions - they can be simplified and shared (gri 2/25/2000) #ifdef ASSERT __ ld(G5_method, Method::access_flags_offset(), Gtmp1); - { - Label L; + { Label L; __ btst(JVM_ACC_NATIVE, Gtmp1); __ br(Assembler::notZero, false, Assembler::pt, L); __ delayed()->nop(); @@ -1443,7 +1408,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // didn't see any synchronization is progress, and escapes. __ set(_thread_in_native_trans, G3_scratch); __ st(G3_scratch, thread_state); - if(os::is_MP()) { + if (os::is_MP()) { if (UseMembar) { // Force this write out before the read below __ membar(Assembler::StoreLoad); @@ -1483,12 +1448,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // Move the result handler address __ mov(Lscratch, G3_scratch); // return possible result to the outer frame -#ifndef __LP64 - __ mov(O0, I0); - __ restore(O1, G0, O1); -#else __ restore(O0, G0, O0); -#endif /* __LP64 */ // Move result handler to expected register __ mov(G3_scratch, Lscratch); @@ -1511,8 +1471,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { // If we have an oop result store it where it will be safe for any further gc // until we return now that we've released the handle it might be protected by - { - Label no_oop, store_result; + { Label no_oop, store_result; __ set((intptr_t)AbstractInterpreter::result_handler(T_OBJECT), G3_scratch); __ cmp_and_brx_short(G3_scratch, Lscratch, Assembler::notEqual, Assembler::pt, no_oop); @@ -1568,21 +1527,9 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { restore_native_result(); } -#if defined(COMPILER2) && !defined(_LP64) - - // C2 expects long results in G1 we can't tell if we're returning to interpreted - // or compiled so just be safe. - - __ sllx(O0, 32, G1); // Shift bits into high G1 - __ srl (O1, 0, O1); // Zero extend O1 - __ or3 (O1, G1, G1); // OR 64 bits into G1 - -#endif /* COMPILER2 && !_LP64 */ - // dispose of return address and remove activation #ifdef ASSERT - { - Label ok; + { Label ok; __ cmp_and_brx_short(I5_savedSP, FP, Assembler::greaterEqualUnsigned, Assembler::pt, ok); __ stop("bad I5_savedSP value"); __ should_not_reach_here(); @@ -1592,15 +1539,12 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { __ jmp(Lscratch, 0); __ delayed()->nop(); - if (inc_counter) { // handle invocation counter overflow __ bind(invocation_counter_overflow); generate_counter_overflow(Lcontinue); } - - return entry; } @@ -1630,8 +1574,7 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { // rethink these assertions - they can be simplified and shared (gri 2/25/2000) #ifdef ASSERT __ ld(G5_method, Method::access_flags_offset(), Gtmp1); - { - Label L; + { Label L; __ btst(JVM_ACC_NATIVE, Gtmp1); __ br(Assembler::zero, false, Assembler::pt, L); __ delayed()->nop(); @@ -1651,11 +1594,6 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { generate_fixed_frame(false); -#ifdef FAST_DISPATCH - __ set((intptr_t)Interpreter::dispatch_table(), IdispatchTables); - // set bytecode dispatch table base -#endif - // // Code to initialize the extra (i.e. non-parm) locals // @@ -1768,7 +1706,6 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { generate_counter_overflow(Lcontinue); } - return entry; } @@ -1888,8 +1825,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { } #if INCLUDE_JVMTI - { - Label L_done; + { Label L_done; __ ldub(Address(Lbcp, 0), G1_scratch); // Load current bytecode __ cmp_and_br_short(G1_scratch, Bytecodes::_invokestatic, Assembler::notEqual, Assembler::pn, L_done); @@ -1929,7 +1865,7 @@ void TemplateInterpreterGenerator::generate_throw_exception() { __ get_vm_result(Oexception); __ verify_oop(Oexception); - const int return_reg_adjustment = frame::pc_return_offset; + const int return_reg_adjustment = frame::pc_return_offset; Address issuing_pc_addr(I7, return_reg_adjustment); // We are done with this activation frame; find out where to go next. diff --git a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp index f828aa0e370..af53a865318 100644 --- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -248,12 +248,7 @@ void TemplateTable::iconst(int value) { void TemplateTable::lconst(int value) { transition(vtos, ltos); assert(value >= 0, "check this code"); -#ifdef _LP64 __ set(value, Otos_l); -#else - __ set(value, Otos_l2); - __ clr( Otos_l1); -#endif } @@ -406,24 +401,12 @@ void TemplateTable::ldc2_w() { // Check out Conversions.java for an example. // Also ConstantPool::header_size() is 20, which makes it very difficult // to double-align double on the constant pool. SG, 11/7/97 -#ifdef _LP64 __ ldf(FloatRegisterImpl::D, G3_scratch, base_offset, Ftos_d); -#else - FloatRegister f = Ftos_d; - __ ldf(FloatRegisterImpl::S, G3_scratch, base_offset, f); - __ ldf(FloatRegisterImpl::S, G3_scratch, base_offset + sizeof(jdouble)/2, - f->successor()); -#endif __ push(dtos); __ ba_short(exit); __ bind(Long); -#ifdef _LP64 __ ldx(G3_scratch, base_offset, Otos_l); -#else - __ ld(G3_scratch, base_offset, Otos_l); - __ ld(G3_scratch, base_offset + sizeof(jlong)/2, Otos_l->successor()); -#endif __ push(ltos); __ bind(exit); @@ -1128,19 +1111,11 @@ void TemplateTable::lop2(Operation op) { transition(ltos, ltos); __ pop_l(O2); switch (op) { -#ifdef _LP64 case add: __ add(O2, Otos_l, Otos_l); break; case sub: __ sub(O2, Otos_l, Otos_l); break; case _and: __ and3(O2, Otos_l, Otos_l); break; case _or: __ or3(O2, Otos_l, Otos_l); break; case _xor: __ xor3(O2, Otos_l, Otos_l); break; -#else - case add: __ addcc(O3, Otos_l2, Otos_l2); __ addc(O2, Otos_l1, Otos_l1); break; - case sub: __ subcc(O3, Otos_l2, Otos_l2); __ subc(O2, Otos_l1, Otos_l1); break; - case _and: __ and3(O3, Otos_l2, Otos_l2); __ and3(O2, Otos_l1, Otos_l1); break; - case _or: __ or3(O3, Otos_l2, Otos_l2); __ or3(O2, Otos_l1, Otos_l1); break; - case _xor: __ xor3(O3, Otos_l2, Otos_l2); __ xor3(O2, Otos_l1, Otos_l1); break; -#endif default: ShouldNotReachHere(); } } @@ -1171,14 +1146,10 @@ void TemplateTable::idiv() { Label regular; __ cmp(Otos_i, -1); __ br(Assembler::notEqual, false, Assembler::pt, regular); -#ifdef _LP64 // Don't put set in delay slot // Set will turn into multiple instructions in 64 bit mode __ delayed()->nop(); __ set(min_int, G4_scratch); -#else - __ delayed()->set(min_int, G4_scratch); -#endif Label done; __ cmp(O1, G4_scratch); __ br(Assembler::equal, true, Assembler::pt, done); @@ -1202,11 +1173,7 @@ void TemplateTable::irem() { void TemplateTable::lmul() { transition(ltos, ltos); __ pop_l(O2); -#ifdef _LP64 __ mulx(Otos_l, O2, Otos_l); -#else - __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::lmul)); -#endif } @@ -1216,15 +1183,9 @@ void TemplateTable::ldiv() { // check for zero __ pop_l(O2); -#ifdef _LP64 __ tst(Otos_l); __ throw_if_not_xcc( Assembler::notZero, Interpreter::_throw_ArithmeticException_entry, G3_scratch); __ sdivx(O2, Otos_l, Otos_l); -#else - __ orcc(Otos_l1, Otos_l2, G0); - __ throw_if_not_icc( Assembler::notZero, Interpreter::_throw_ArithmeticException_entry, G3_scratch); - __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::ldiv)); -#endif } @@ -1233,17 +1194,11 @@ void TemplateTable::lrem() { // check for zero __ pop_l(O2); -#ifdef _LP64 __ tst(Otos_l); __ throw_if_not_xcc( Assembler::notZero, Interpreter::_throw_ArithmeticException_entry, G3_scratch); __ sdivx(O2, Otos_l, Otos_l2); __ mulx (Otos_l2, Otos_l, Otos_l2); __ sub (O2, Otos_l2, Otos_l); -#else - __ orcc(Otos_l1, Otos_l2, G0); - __ throw_if_not_icc(Assembler::notZero, Interpreter::_throw_ArithmeticException_entry, G3_scratch); - __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::lrem)); -#endif } @@ -1251,11 +1206,7 @@ void TemplateTable::lshl() { transition(itos, ltos); // %%%% could optimize, fill delay slot or opt for ultra __ pop_l(O2); // shift value in O2, O3 -#ifdef _LP64 __ sllx(O2, Otos_i, Otos_l); -#else - __ lshl(O2, O3, Otos_i, Otos_l1, Otos_l2, O4); -#endif } @@ -1263,11 +1214,7 @@ void TemplateTable::lshr() { transition(itos, ltos); // %%%% see lshl comment __ pop_l(O2); // shift value in O2, O3 -#ifdef _LP64 __ srax(O2, Otos_i, Otos_l); -#else - __ lshr(O2, O3, Otos_i, Otos_l1, Otos_l2, O4); -#endif } @@ -1276,11 +1223,7 @@ void TemplateTable::lushr() { transition(itos, ltos); // %%%% see lshl comment __ pop_l(O2); // shift value in O2, O3 -#ifdef _LP64 __ srlx(O2, Otos_i, Otos_l); -#else - __ lushr(O2, O3, Otos_i, Otos_l1, Otos_l2, O4); -#endif } @@ -1293,15 +1236,9 @@ void TemplateTable::fop2(Operation op) { case div: __ pop_f(F4); __ fdiv(FloatRegisterImpl::S, F4, Ftos_f, Ftos_f); break; case rem: assert(Ftos_f == F0, "just checking"); -#ifdef _LP64 // LP64 calling conventions use F1, F3 for passing 2 floats __ pop_f(F1); __ fmov(FloatRegisterImpl::S, Ftos_f, F3); -#else - __ pop_i(O0); - __ stf(FloatRegisterImpl::S, Ftos_f, __ d_tmp); - __ ld( __ d_tmp, O1 ); -#endif __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::frem)); assert( Ftos_f == F0, "fix this code" ); break; @@ -1319,18 +1256,9 @@ void TemplateTable::dop2(Operation op) { case mul: __ pop_d(F4); __ fmul(FloatRegisterImpl::D, F4, Ftos_d, Ftos_d); break; case div: __ pop_d(F4); __ fdiv(FloatRegisterImpl::D, F4, Ftos_d, Ftos_d); break; case rem: -#ifdef _LP64 // Pass arguments in D0, D2 __ fmov(FloatRegisterImpl::D, Ftos_f, F2 ); __ pop_d( F0 ); -#else - // Pass arguments in O0O1, O2O3 - __ stf(FloatRegisterImpl::D, Ftos_f, __ d_tmp); - __ ldd( __ d_tmp, O2 ); - __ pop_d(Ftos_f); - __ stf(FloatRegisterImpl::D, Ftos_f, __ d_tmp); - __ ldd( __ d_tmp, O0 ); -#endif __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::drem)); assert( Ftos_d == F0, "fix this code" ); break; @@ -1348,11 +1276,7 @@ void TemplateTable::ineg() { void TemplateTable::lneg() { transition(ltos, ltos); -#ifdef _LP64 __ sub(G0, Otos_l, Otos_l); -#else - __ lneg(Otos_l1, Otos_l2); -#endif } @@ -1437,15 +1361,8 @@ void TemplateTable::convert() { Label done; switch (bytecode()) { case Bytecodes::_i2l: -#ifdef _LP64 // Sign extend the 32 bits __ sra ( Otos_i, 0, Otos_l ); -#else - __ addcc(Otos_i, 0, Otos_l2); - __ br(Assembler::greaterEqual, true, Assembler::pt, done); - __ delayed()->clr(Otos_l1); - __ set(~0, Otos_l1); -#endif break; case Bytecodes::_i2f: @@ -1476,12 +1393,8 @@ void TemplateTable::convert() { break; case Bytecodes::_l2i: -#ifndef _LP64 - __ mov(Otos_l2, Otos_i); -#else // Sign-extend into the high 32 bits __ sra(Otos_l, 0, Otos_i); -#endif break; case Bytecodes::_l2f: @@ -1512,11 +1425,7 @@ void TemplateTable::convert() { case Bytecodes::_f2l: // must uncache tos __ push_f(); -#ifdef _LP64 __ pop_f(F1); -#else - __ pop_i(O0); -#endif __ call_VM_leaf(Lscratch, CAST_FROM_FN_PTR(address, SharedRuntime::f2l)); break; @@ -1528,13 +1437,8 @@ void TemplateTable::convert() { case Bytecodes::_d2l: // must uncache tos __ push_d(); -#ifdef _LP64 // LP64 calling conventions pass first double arg in D0 __ pop_d( Ftos_d ); -#else - __ pop_i( O0 ); - __ pop_i( O1 ); -#endif __ call_VM_leaf(Lscratch, bytecode() == Bytecodes::_d2i ? CAST_FROM_FN_PTR(address, SharedRuntime::d2i) @@ -1554,13 +1458,8 @@ void TemplateTable::convert() { void TemplateTable::lcmp() { transition(ltos, itos); -#ifdef _LP64 __ pop_l(O1); // pop off value 1, value 2 is in O0 __ lcmp( O1, Otos_l, Otos_i ); -#else - __ pop_l(O2); // cmp O2,3 to O0,1 - __ lcmp( O2, O3, Otos_l1, Otos_l2, Otos_i ); -#endif } @@ -1756,7 +1655,6 @@ void TemplateTable::ret() { __ access_local_returnAddress(G3_scratch, Otos_i); // Otos_i contains the bci, compute the bcp from that -#ifdef _LP64 #ifdef ASSERT // jsr result was labeled as an 'itos' not an 'atos' because we cannot GC // the result. The return address (really a BCI) was stored with an @@ -1771,7 +1669,6 @@ void TemplateTable::ret() { __ stop("BCI is in the wrong register half?"); __ bind (zzz) ; } -#endif #endif __ profile_ret(vtos, Otos_i, G4_scratch); @@ -1808,10 +1705,8 @@ void TemplateTable::tableswitch() { // load lo, hi __ ld(O1, 1 * BytesPerInt, O2); // Low Byte __ ld(O1, 2 * BytesPerInt, O3); // High Byte -#ifdef _LP64 // Sign extend the 32 bits __ sra ( Otos_i, 0, Otos_i ); -#endif /* _LP64 */ // check against lo & hi __ cmp( Otos_i, O2); @@ -3346,9 +3241,7 @@ void TemplateTable::_new() { __ br(Assembler::notEqual, false, Assembler::pn, slow_case); __ delayed()->sll(Roffset, LogBytesPerWord, Roffset); // get InstanceKlass - //__ sll(Roffset, LogBytesPerWord, Roffset); // executed in delay slot - __ add(Roffset, sizeof(ConstantPool), Roffset); - __ ld_ptr(Rscratch, Roffset, RinstanceKlass); + __ load_resolved_klass_at_offset(Rscratch, Roffset, RinstanceKlass); // make sure klass is fully initialized: __ ldub(RinstanceKlass, in_bytes(InstanceKlass::init_state_offset()), G3_scratch); @@ -3400,11 +3293,7 @@ void TemplateTable::_new() { // Check if tlab should be discarded (refill_waste_limit >= free) __ ld_ptr(G2_thread, in_bytes(JavaThread::tlab_refill_waste_limit_offset()), RtlabWasteLimitValue); __ sub(RendValue, RoldTopValue, RfreeValue); -#ifdef _LP64 __ srlx(RfreeValue, LogHeapWordSize, RfreeValue); -#else - __ srl(RfreeValue, LogHeapWordSize, RfreeValue); -#endif __ cmp_and_brx_short(RtlabWasteLimitValue, RfreeValue, Assembler::greaterEqualUnsigned, Assembler::pt, slow_case); // tlab waste is small // increment waste limit to prevent getting stuck on this slow path @@ -3574,8 +3463,9 @@ void TemplateTable::checkcast() { // Extract target class from constant pool __ bind(quicked); - __ add(Roffset, sizeof(ConstantPool), Roffset); - __ ld_ptr(Lscratch, Roffset, RspecifiedKlass); + __ load_resolved_klass_at_offset(Lscratch, Roffset, RspecifiedKlass); + + __ bind(resolved); __ load_klass(Otos_i, RobjKlass); // get value klass @@ -3631,9 +3521,9 @@ void TemplateTable::instanceof() { // Extract target class from constant pool __ bind(quicked); - __ add(Roffset, sizeof(ConstantPool), Roffset); __ get_constant_pool(Lscratch); - __ ld_ptr(Lscratch, Roffset, RspecifiedKlass); + __ load_resolved_klass_at_offset(Lscratch, Roffset, RspecifiedKlass); + __ bind(resolved); __ load_klass(Otos_i, RobjKlass); // get value klass diff --git a/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp b/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp index 2c84cece3cc..aa21dbdb2db 100644 --- a/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/vmStructs_sparc.hpp @@ -71,28 +71,43 @@ declare_c2_constant(R_G5_num) \ declare_c2_constant(R_G6_num) \ declare_c2_constant(R_G7_num) \ - declare_constant(VM_Version::vis1_instructions_m) \ - declare_constant(VM_Version::vis2_instructions_m) \ - declare_constant(VM_Version::vis3_instructions_m) \ - declare_constant(VM_Version::cbcond_instructions_m) \ - declare_constant(VM_Version::v8_instructions_m) \ - declare_constant(VM_Version::hardware_mul32_m) \ - declare_constant(VM_Version::hardware_div32_m) \ - declare_constant(VM_Version::hardware_fsmuld_m) \ - declare_constant(VM_Version::hardware_popc_m) \ - declare_constant(VM_Version::v9_instructions_m) \ - declare_constant(VM_Version::sun4v_m) \ - declare_constant(VM_Version::blk_init_instructions_m) \ - declare_constant(VM_Version::fmaf_instructions_m) \ - declare_constant(VM_Version::sparc64_family_m) \ - declare_constant(VM_Version::M_family_m) \ - declare_constant(VM_Version::T_family_m) \ - declare_constant(VM_Version::T1_model_m) \ - declare_constant(VM_Version::sparc5_instructions_m) \ - declare_constant(VM_Version::aes_instructions_m) \ - declare_constant(VM_Version::sha1_instruction_m) \ - declare_constant(VM_Version::sha256_instruction_m) \ - declare_constant(VM_Version::sha512_instruction_m) + declare_constant(VM_Version::ISA_V9) \ + declare_constant(VM_Version::ISA_POPC) \ + declare_constant(VM_Version::ISA_VIS1) \ + declare_constant(VM_Version::ISA_VIS2) \ + declare_constant(VM_Version::ISA_BLK_INIT) \ + declare_constant(VM_Version::ISA_FMAF) \ + declare_constant(VM_Version::ISA_VIS3) \ + declare_constant(VM_Version::ISA_HPC) \ + declare_constant(VM_Version::ISA_IMA) \ + declare_constant(VM_Version::ISA_AES) \ + declare_constant(VM_Version::ISA_DES) \ + declare_constant(VM_Version::ISA_KASUMI) \ + declare_constant(VM_Version::ISA_CAMELLIA) \ + declare_constant(VM_Version::ISA_MD5) \ + declare_constant(VM_Version::ISA_SHA1) \ + declare_constant(VM_Version::ISA_SHA256) \ + declare_constant(VM_Version::ISA_SHA512) \ + declare_constant(VM_Version::ISA_MPMUL) \ + declare_constant(VM_Version::ISA_MONT) \ + declare_constant(VM_Version::ISA_PAUSE) \ + declare_constant(VM_Version::ISA_CBCOND) \ + declare_constant(VM_Version::ISA_CRC32C) \ + declare_constant(VM_Version::ISA_VIS3B) \ + declare_constant(VM_Version::ISA_ADI) \ + declare_constant(VM_Version::ISA_SPARC5) \ + declare_constant(VM_Version::ISA_MWAIT) \ + declare_constant(VM_Version::ISA_XMPMUL) \ + declare_constant(VM_Version::ISA_XMONT) \ + declare_constant(VM_Version::ISA_PAUSE_NSEC) \ + declare_constant(VM_Version::ISA_VAMASK) \ + declare_constant(VM_Version::CPU_FAST_IDIV) \ + declare_constant(VM_Version::CPU_FAST_RDPC) \ + declare_constant(VM_Version::CPU_FAST_BIS) \ + declare_constant(VM_Version::CPU_FAST_LD) \ + declare_constant(VM_Version::CPU_FAST_CMOVE) \ + declare_constant(VM_Version::CPU_FAST_IND_BR) \ + declare_constant(VM_Version::CPU_BLK_ZEROING) #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 770ca6bf197..37203221f71 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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,13 +25,17 @@ #include "precompiled.hpp" #include "asm/macroAssembler.inline.hpp" #include "logging/log.hpp" +#include "logging/logStream.hpp" #include "memory/resourceArea.hpp" +#include "prims/jvm.h" #include "runtime/java.hpp" #include "runtime/os.hpp" #include "runtime/stubCodeGenerator.hpp" #include "vm_version_sparc.hpp" -unsigned int VM_Version::_L2_data_cache_line_size = 0; +#include + +uint VM_Version::_L2_data_cache_line_size = 0; void VM_Version::initialize() { assert(_features != 0, "System pre-initialization is not complete."); @@ -42,97 +46,110 @@ void VM_Version::initialize() { PrefetchFieldsAhead = prefetch_fields_ahead(); // Allocation prefetch settings - intx cache_line_size = prefetch_data_size(); - if( cache_line_size > AllocatePrefetchStepSize ) - AllocatePrefetchStepSize = cache_line_size; AllocatePrefetchDistance = allocate_prefetch_distance(); AllocatePrefetchStyle = allocate_prefetch_style(); - if (!has_blk_init() || cache_line_size <= 0) { - if (AllocatePrefetchInstr == 1) { + intx cache_line_size = prefetch_data_size(); + + if (FLAG_IS_DEFAULT(AllocatePrefetchStepSize)) { + AllocatePrefetchStepSize = MAX2(AllocatePrefetchStepSize, cache_line_size); + } + + if (AllocatePrefetchInstr == 1) { + if (!has_blk_init()) { warning("BIS instructions required for AllocatePrefetchInstr 1 unavailable"); FLAG_SET_DEFAULT(AllocatePrefetchInstr, 0); } + if (cache_line_size <= 0) { + warning("Cache-line size must be known for AllocatePrefetchInstr 1 to work"); + FLAG_SET_DEFAULT(AllocatePrefetchInstr, 0); + } } - UseSSE = 0; // Only on x86 and x64 + UseSSE = false; // Only used on x86 and x64. - _supports_cx8 = has_v9(); - _supports_atomic_getset4 = true; // swap instruction + _supports_cx8 = true; // All SPARC V9 implementations. + _supports_atomic_getset4 = true; // Using the 'swap' instruction. - if (is_niagara()) { - // Indirect branch is the same cost as direct - if (FLAG_IS_DEFAULT(UseInlineCaches)) { - FLAG_SET_DEFAULT(UseInlineCaches, false); - } - // Align loops on a single instruction boundary. - if (FLAG_IS_DEFAULT(OptoLoopAlignment)) { - FLAG_SET_DEFAULT(OptoLoopAlignment, 4); - } -#ifdef _LP64 - // 32-bit oops don't make sense for the 64-bit VM on sparc - // since the 32-bit VM has the same registers and smaller objects. - Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); - Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes); -#endif // _LP64 -#ifdef COMPILER2 - // Indirect branch is the same cost as direct - if (FLAG_IS_DEFAULT(UseJumpTables)) { - FLAG_SET_DEFAULT(UseJumpTables, true); - } - // Single-issue, so entry and loop tops are - // aligned on a single instruction boundary - if (FLAG_IS_DEFAULT(InteriorEntryAlignment)) { - FLAG_SET_DEFAULT(InteriorEntryAlignment, 4); - } - if (is_niagara_plus()) { - if (has_blk_init() && (cache_line_size > 0) && UseTLAB && - FLAG_IS_DEFAULT(AllocatePrefetchInstr)) { - if (!has_sparc5_instr()) { - // Use BIS instruction for TLAB allocation prefetch - // on Niagara plus processors other than those based on CoreS4 - FLAG_SET_DEFAULT(AllocatePrefetchInstr, 1); - } else { - // On CoreS4 processors use prefetch instruction - // to avoid partial RAW issue, also use prefetch style 3 - FLAG_SET_DEFAULT(AllocatePrefetchInstr, 0); - if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) { - FLAG_SET_DEFAULT(AllocatePrefetchStyle, 3); - } - } - } - if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) { - if (AllocatePrefetchInstr == 0) { - // Use different prefetch distance without BIS - FLAG_SET_DEFAULT(AllocatePrefetchDistance, 256); - } else { - // Use smaller prefetch distance with BIS - FLAG_SET_DEFAULT(AllocatePrefetchDistance, 64); - } - } - if (is_T4()) { - // Double number of prefetched cache lines on T4 - // since L2 cache line size is smaller (32 bytes). - if (FLAG_IS_DEFAULT(AllocatePrefetchLines)) { - FLAG_SET_ERGO(intx, AllocatePrefetchLines, AllocatePrefetchLines*2); - } - if (FLAG_IS_DEFAULT(AllocateInstancePrefetchLines)) { - FLAG_SET_ERGO(intx, AllocateInstancePrefetchLines, AllocateInstancePrefetchLines*2); - } - } - } - - if (AllocatePrefetchInstr == 1) { - // Use allocation prefetch style 3 because BIS instructions - // require aligned memory addresses. - FLAG_SET_DEFAULT(AllocatePrefetchStyle, 3); - } -#endif /* COMPILER2 */ + if (has_fast_ind_br() && FLAG_IS_DEFAULT(UseInlineCaches)) { + // Indirect and direct branches are cost equivalent. + FLAG_SET_DEFAULT(UseInlineCaches, false); + } + // Align loops on the proper instruction boundary to fill the instruction + // fetch buffer. + if (FLAG_IS_DEFAULT(OptoLoopAlignment)) { + FLAG_SET_DEFAULT(OptoLoopAlignment, VM_Version::insn_fetch_alignment); } + // 32-bit oops don't make sense for the 64-bit VM on SPARC since the 32-bit + // VM has the same registers and smaller objects. + Universe::set_narrow_oop_shift(LogMinObjAlignmentInBytes); + Universe::set_narrow_klass_shift(LogKlassAlignmentInBytes); + +#ifdef COMPILER2 + if (has_fast_ind_br() && FLAG_IS_DEFAULT(UseJumpTables)) { + // Indirect and direct branches are cost equivalent. + FLAG_SET_DEFAULT(UseJumpTables, true); + } + // Entry and loop tops are aligned to fill the instruction fetch buffer. + if (FLAG_IS_DEFAULT(InteriorEntryAlignment)) { + FLAG_SET_DEFAULT(InteriorEntryAlignment, VM_Version::insn_fetch_alignment); + } + if (UseTLAB && cache_line_size > 0 && + FLAG_IS_DEFAULT(AllocatePrefetchInstr)) { + if (has_fast_bis()) { + // Use BIS instruction for TLAB allocation prefetch. + FLAG_SET_DEFAULT(AllocatePrefetchInstr, 1); + } + else if (has_sparc5()) { + // Use prefetch instruction to avoid partial RAW issue on Core S4 processors, + // also use prefetch style 3. + FLAG_SET_DEFAULT(AllocatePrefetchInstr, 0); + if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) { + FLAG_SET_DEFAULT(AllocatePrefetchStyle, 3); + } + } + } + if (AllocatePrefetchInstr == 1) { + // Use allocation prefetch style 3 because BIS instructions require + // aligned memory addresses. + FLAG_SET_DEFAULT(AllocatePrefetchStyle, 3); + } + if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) { + if (AllocatePrefetchInstr == 0) { + // Use different prefetch distance without BIS + FLAG_SET_DEFAULT(AllocatePrefetchDistance, 256); + } else { + // Use smaller prefetch distance with BIS + FLAG_SET_DEFAULT(AllocatePrefetchDistance, 64); + } + } + + // We increase the number of prefetched cache lines, to use just a bit more + // aggressive approach, when the L2-cache line size is small (32 bytes), or + // when running on newer processor implementations, such as the Core S4. + bool inc_prefetch = cache_line_size > 0 && (cache_line_size < 64 || has_sparc5()); + + if (inc_prefetch) { + // We use a factor two for small cache line sizes (as before) but a slightly + // more conservative increase when running on more recent hardware that will + // benefit from just a bit more aggressive prefetching. + if (FLAG_IS_DEFAULT(AllocatePrefetchLines)) { + const int ap_lns = AllocatePrefetchLines; + const int ap_inc = cache_line_size < 64 ? ap_lns : (ap_lns + 1) / 2; + FLAG_SET_ERGO(intx, AllocatePrefetchLines, ap_lns + ap_inc); + } + if (FLAG_IS_DEFAULT(AllocateInstancePrefetchLines)) { + const int ip_lns = AllocateInstancePrefetchLines; + const int ip_inc = cache_line_size < 64 ? ip_lns : (ip_lns + 1) / 2; + FLAG_SET_ERGO(intx, AllocateInstancePrefetchLines, ip_lns + ip_inc); + } + } +#endif /* COMPILER2 */ + // Use hardware population count instruction if available. - if (has_hardware_popc()) { + if (has_popc()) { if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { FLAG_SET_DEFAULT(UsePopCountInstruction, true); } @@ -141,7 +158,7 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UsePopCountInstruction, false); } - // T4 and newer Sparc cpus have new compare and branch instruction. + // Use compare and branch instructions if available. if (has_cbcond()) { if (FLAG_IS_DEFAULT(UseCBCond)) { FLAG_SET_DEFAULT(UseCBCond, true); @@ -152,7 +169,8 @@ void VM_Version::initialize() { } assert(BlockZeroingLowLimit > 0, "invalid value"); - if (has_block_zeroing() && cache_line_size > 0) { + + if (has_blk_zeroing() && cache_line_size > 0) { if (FLAG_IS_DEFAULT(UseBlockZeroing)) { FLAG_SET_DEFAULT(UseBlockZeroing, true); } @@ -162,7 +180,8 @@ void VM_Version::initialize() { } assert(BlockCopyLowLimit > 0, "invalid value"); - if (has_block_zeroing() && cache_line_size > 0) { // has_blk_init() && is_T4(): core's local L2 cache + + if (has_blk_zeroing() && cache_line_size > 0) { if (FLAG_IS_DEFAULT(UseBlockCopy)) { FLAG_SET_DEFAULT(UseBlockCopy, true); } @@ -172,7 +191,6 @@ void VM_Version::initialize() { } #ifdef COMPILER2 - // T4 and newer Sparc cpus have fast RDPC. if (has_fast_rdpc() && FLAG_IS_DEFAULT(UseRDPCForConstantTableBase)) { FLAG_SET_DEFAULT(UseRDPCForConstantTableBase, true); } @@ -189,44 +207,67 @@ void VM_Version::initialize() { assert((OptoLoopAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size"); char buf[512]; - jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", - (has_v9() ? ", v9" : (has_v8() ? ", v8" : "")), - (has_hardware_popc() ? ", popc" : ""), - (has_vis1() ? ", vis1" : ""), - (has_vis2() ? ", vis2" : ""), - (has_vis3() ? ", vis3" : ""), - (has_blk_init() ? ", blk_init" : ""), - (has_cbcond() ? ", cbcond" : ""), - (has_aes() ? ", aes" : ""), - (has_sha1() ? ", sha1" : ""), - (has_sha256() ? ", sha256" : ""), - (has_sha512() ? ", sha512" : ""), - (has_crc32c() ? ", crc32c" : ""), - (is_ultra3() ? ", ultra3" : ""), - (has_sparc5_instr() ? ", sparc5" : ""), - (is_sun4v() ? ", sun4v" : ""), - (is_niagara_plus() ? ", niagara_plus" : (is_niagara() ? ", niagara" : "")), - (is_sparc64() ? ", sparc64" : ""), - (!has_hardware_mul32() ? ", no-mul32" : ""), - (!has_hardware_div32() ? ", no-div32" : ""), - (!has_hardware_fsmuld() ? ", no-fsmuld" : "")); + jio_snprintf(buf, sizeof(buf), + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + (has_v9() ? "v9" : ""), + (has_popc() ? ", popc" : ""), + (has_vis1() ? ", vis1" : ""), + (has_vis2() ? ", vis2" : ""), + (has_blk_init() ? ", blk_init" : ""), + (has_fmaf() ? ", fmaf" : ""), + (has_hpc() ? ", hpc" : ""), + (has_ima() ? ", ima" : ""), + (has_aes() ? ", aes" : ""), + (has_des() ? ", des" : ""), + (has_kasumi() ? ", kas" : ""), + (has_camellia() ? ", cam" : ""), + (has_md5() ? ", md5" : ""), + (has_sha1() ? ", sha1" : ""), + (has_sha256() ? ", sha256" : ""), + (has_sha512() ? ", sha512" : ""), + (has_mpmul() ? ", mpmul" : ""), + (has_mont() ? ", mont" : ""), + (has_pause() ? ", pause" : ""), + (has_cbcond() ? ", cbcond" : ""), + (has_crc32c() ? ", crc32c" : ""), - // buf is started with ", " or is empty - _features_string = os::strdup(strlen(buf) > 2 ? buf + 2 : buf); + (has_athena_plus() ? ", athena_plus" : ""), + (has_vis3b() ? ", vis3b" : ""), + (has_adi() ? ", adi" : ""), + (has_sparc5() ? ", sparc5" : ""), + (has_mwait() ? ", mwait" : ""), + (has_xmpmul() ? ", xmpmul" : ""), + (has_xmont() ? ", xmont" : ""), + (has_pause_nsec() ? ", pause_nsec" : ""), + (has_vamask() ? ", vamask" : ""), - // UseVIS is set to the smallest of what hardware supports and what - // the command line requires. I.e., you cannot set UseVIS to 3 on - // older UltraSparc which do not support it. - if (UseVIS > 3) UseVIS=3; - if (UseVIS < 0) UseVIS=0; + (has_fast_idiv() ? ", *idiv" : ""), + (has_fast_rdpc() ? ", *rdpc" : ""), + (has_fast_bis() ? ", *bis" : ""), + (has_fast_ld() ? ", *ld" : ""), + (has_fast_cmove() ? ", *cmove" : ""), + (has_fast_ind_br() ? ", *ind_br" : ""), + (has_blk_zeroing() ? ", *blk_zeroing" : "")); + + assert(strlen(buf) >= 2, "must be"); + + _features_string = os::strdup(buf); + + log_info(os, cpu)("SPARC features detected: %s", _features_string); + + // UseVIS is set to the smallest of what hardware supports and what the command + // line requires, i.e. you cannot set UseVIS to 3 on older UltraSparc which do + // not support it. + + if (UseVIS > 3) UseVIS = 3; + if (UseVIS < 0) UseVIS = 0; if (!has_vis3()) // Drop to 2 if no VIS3 support - UseVIS = MIN2((intx)2,UseVIS); + UseVIS = MIN2((intx)2, UseVIS); if (!has_vis2()) // Drop to 1 if no VIS2 support - UseVIS = MIN2((intx)1,UseVIS); + UseVIS = MIN2((intx)1, UseVIS); if (!has_vis1()) // Drop to 0 if no VIS1 support UseVIS = 0; - // SPARC T4 and above should have support for AES instructions if (has_aes()) { if (FLAG_IS_DEFAULT(UseAES)) { FLAG_SET_DEFAULT(UseAES, true); @@ -277,12 +318,16 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseGHASHIntrinsics, false); } - if (UseFMA) { + if (has_fmaf()) { + if (FLAG_IS_DEFAULT(UseFMA)) { + UseFMA = true; + } + } else if (UseFMA) { warning("FMA instructions are not available on this CPU"); FLAG_SET_DEFAULT(UseFMA, false); } - // SHA1, SHA256, and SHA512 instructions were added to SPARC T-series at different times + // SHA1, SHA256, and SHA512 instructions were added to SPARC at different times if (has_sha1() || has_sha256() || has_sha512()) { if (UseVIS > 0) { // SHA intrinsics use VIS1 instructions if (FLAG_IS_DEFAULT(UseSHA)) { @@ -330,7 +375,6 @@ void VM_Version::initialize() { FLAG_SET_DEFAULT(UseSHA, false); } - // SPARC T4 and above should have support for CRC32C instruction if (has_crc32c()) { if (UseVIS > 2) { // CRC32C intrinsics use VIS3 instructions if (FLAG_IS_DEFAULT(UseCRC32CIntrinsics)) { @@ -383,7 +427,8 @@ void VM_Version::initialize() { if (log_is_enabled(Info, os, cpu)) { ResourceMark rm; - outputStream* log = Log(os, cpu)::info_stream(); + LogStream ls(Log(os, cpu)::info()); + outputStream* log = &ls; log->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); log->print_cr("L2 data cache line size: %u", L2_data_cache_line_size()); log->print("Allocation"); @@ -418,96 +463,42 @@ void VM_Version::initialize() { } void VM_Version::print_features() { - tty->print_cr("Version:%s", _features); + tty->print("ISA features [0x%0" PRIx64 "]:", _features); + if (_features_string != NULL) { + tty->print(" %s", _features_string); + } + tty->cr(); } -int VM_Version::determine_features() { - if (UseV8InstrsOnly) { - log_info(os, cpu)("Version is Forced-V8"); - return generic_v8_m; +void VM_Version::determine_features() { + platform_features(); // platform_features() is os_arch specific. + + assert(has_v9(), "must be"); + + if (UseNiagaraInstrs) { // Limit code generation to Niagara. + _features &= niagara1_msk; } - - int features = platform_features(unknown_m); // platform_features() is os_arch specific - - if (features == unknown_m) { - features = generic_v9_m; - log_info(os)("Cannot recognize SPARC version. Default to V9"); - } - - assert(is_T_family(features) == is_niagara(features), "Niagara should be T series"); - if (UseNiagaraInstrs) { // Force code generation for Niagara - if (is_T_family(features)) { - // Happy to accomodate... - } else { - log_info(os, cpu)("Version is Forced-Niagara"); - features |= T_family_m; - } - } else { - if (is_T_family(features) && !FLAG_IS_DEFAULT(UseNiagaraInstrs)) { - log_info(os, cpu)("Version is Forced-Not-Niagara"); - features &= ~(T_family_m | T1_model_m); - } else { - // Happy to accomodate... - } - } - - return features; } static uint64_t saved_features = 0; void VM_Version::allow_all() { saved_features = _features; - _features = all_features_m; + _features = full_feature_msk; } void VM_Version::revert() { _features = saved_features; } +/* Determine a suitable number of threads on this particular machine. + * + * FIXME: Simply checking the processor family is insufficient. + */ unsigned int VM_Version::calc_parallel_worker_threads() { - unsigned int result; - if (is_M_series() || is_S_series()) { - // for now, use same gc thread calculation for M-series and S-series as for - // niagara-plus. In future, we may want to tweak parameters for - // nof_parallel_worker_thread - result = nof_parallel_worker_threads(5, 16, 8); - } else if (is_niagara_plus()) { - result = nof_parallel_worker_threads(5, 16, 8); - } else { - result = nof_parallel_worker_threads(5, 8, 8); - } - return result; -} - - -int VM_Version::parse_features(const char* implementation) { - int features = unknown_m; - // Convert to UPPER case before compare. - char* impl = os::strdup_check_oom(implementation); - - for (int i = 0; impl[i] != 0; i++) - impl[i] = (char)toupper((uint)impl[i]); - - if (strstr(impl, "SPARC64") != NULL) { - features |= sparc64_family_m; - } else if (strstr(impl, "SPARC-M") != NULL) { - // M-series SPARC is based on T-series. - features |= (M_family_m | T_family_m); - } else if (strstr(impl, "SPARC-S") != NULL) { - // S-series SPARC is based on T-series. - features |= (S_family_m | T_family_m); - } else if (strstr(impl, "SPARC-T") != NULL) { - features |= T_family_m; - if (strstr(impl, "SPARC-T1") != NULL) { - features |= T1_model_m; - } - } else if (strstr(impl, "SUN4V-CPU") != NULL) { - // Generic or migration class LDOM - features |= T_family_m; - } else { - log_info(os, cpu)("Failed to parse CPU implementation = '%s'", impl); - } - os::free((void*)impl); - return features; + const int num = 5; + const int den = is_post_niagara() ? 16 : 8; + const int threshold = 8; + + return nof_parallel_worker_threads(num, den, threshold); } diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp index f5cb00d75a7..58e8283d6ee 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp @@ -33,185 +33,296 @@ class VM_Version: public Abstract_VM_Version { friend class JVMCIVMStructs; protected: - enum Feature_Flag { - v8_instructions = 0, - hardware_mul32 = 1, - hardware_div32 = 2, - hardware_fsmuld = 3, - hardware_popc = 4, - v9_instructions = 5, - vis1_instructions = 6, - vis2_instructions = 7, - sun4v_instructions = 8, - blk_init_instructions = 9, - fmaf_instructions = 10, - vis3_instructions = 11, - cbcond_instructions = 12, - sparc64_family = 13, - M_family = 14, - S_family = 15, - T_family = 16, - T1_model = 17, - sparc5_instructions = 18, - aes_instructions = 19, - sha1_instruction = 20, - sha256_instruction = 21, - sha512_instruction = 22, - crc32c_instruction = 23 + enum { + ISA_V9, + ISA_POPC, + ISA_VIS1, + ISA_VIS2, + ISA_BLK_INIT, + ISA_FMAF, + ISA_VIS3, + ISA_HPC, + ISA_IMA, + ISA_AES, + ISA_DES, + ISA_KASUMI, + ISA_CAMELLIA, + ISA_MD5, + ISA_SHA1, + ISA_SHA256, + ISA_SHA512, + ISA_MPMUL, + ISA_MONT, + ISA_PAUSE, + ISA_CBCOND, + ISA_CRC32C, + + ISA_FJATHPLUS, + ISA_VIS3B, + ISA_ADI, + ISA_SPARC5, + ISA_MWAIT, + ISA_XMPMUL, + ISA_XMONT, + ISA_PAUSE_NSEC, + ISA_VAMASK, + + // Synthesised properties: + + CPU_FAST_IDIV, + CPU_FAST_RDPC, + CPU_FAST_BIS, + CPU_FAST_LD, + CPU_FAST_CMOVE, + CPU_FAST_IND_BR, + CPU_BLK_ZEROING }; - enum Feature_Flag_Set { - unknown_m = 0, - all_features_m = -1, +private: + enum { ISA_last_feature = ISA_VAMASK, + CPU_last_feature = CPU_BLK_ZEROING }; - v8_instructions_m = 1 << v8_instructions, - hardware_mul32_m = 1 << hardware_mul32, - hardware_div32_m = 1 << hardware_div32, - hardware_fsmuld_m = 1 << hardware_fsmuld, - hardware_popc_m = 1 << hardware_popc, - v9_instructions_m = 1 << v9_instructions, - vis1_instructions_m = 1 << vis1_instructions, - vis2_instructions_m = 1 << vis2_instructions, - sun4v_m = 1 << sun4v_instructions, - blk_init_instructions_m = 1 << blk_init_instructions, - fmaf_instructions_m = 1 << fmaf_instructions, - vis3_instructions_m = 1 << vis3_instructions, - cbcond_instructions_m = 1 << cbcond_instructions, - sparc64_family_m = 1 << sparc64_family, - M_family_m = 1 << M_family, - S_family_m = 1 << S_family, - T_family_m = 1 << T_family, - T1_model_m = 1 << T1_model, - sparc5_instructions_m = 1 << sparc5_instructions, - aes_instructions_m = 1 << aes_instructions, - sha1_instruction_m = 1 << sha1_instruction, - sha256_instruction_m = 1 << sha256_instruction, - sha512_instruction_m = 1 << sha512_instruction, - crc32c_instruction_m = 1 << crc32c_instruction, + enum { + ISA_unknown_msk = 0, - generic_v8_m = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m, - generic_v9_m = generic_v8_m | v9_instructions_m, - ultra3_m = generic_v9_m | vis1_instructions_m | vis2_instructions_m, + ISA_v9_msk = UINT64_C(1) << ISA_V9, - // Temporary until we have something more accurate - niagara1_unique_m = sun4v_m, - niagara1_m = generic_v9_m | niagara1_unique_m + ISA_popc_msk = UINT64_C(1) << ISA_POPC, + ISA_vis1_msk = UINT64_C(1) << ISA_VIS1, + ISA_vis2_msk = UINT64_C(1) << ISA_VIS2, + ISA_blk_init_msk = UINT64_C(1) << ISA_BLK_INIT, + ISA_fmaf_msk = UINT64_C(1) << ISA_FMAF, + ISA_vis3_msk = UINT64_C(1) << ISA_VIS3, + ISA_hpc_msk = UINT64_C(1) << ISA_HPC, + ISA_ima_msk = UINT64_C(1) << ISA_IMA, + ISA_aes_msk = UINT64_C(1) << ISA_AES, + ISA_des_msk = UINT64_C(1) << ISA_DES, + ISA_kasumi_msk = UINT64_C(1) << ISA_KASUMI, + ISA_camellia_msk = UINT64_C(1) << ISA_CAMELLIA, + ISA_md5_msk = UINT64_C(1) << ISA_MD5, + ISA_sha1_msk = UINT64_C(1) << ISA_SHA1, + ISA_sha256_msk = UINT64_C(1) << ISA_SHA256, + ISA_sha512_msk = UINT64_C(1) << ISA_SHA512, + ISA_mpmul_msk = UINT64_C(1) << ISA_MPMUL, + ISA_mont_msk = UINT64_C(1) << ISA_MONT, + ISA_pause_msk = UINT64_C(1) << ISA_PAUSE, + ISA_cbcond_msk = UINT64_C(1) << ISA_CBCOND, + ISA_crc32c_msk = UINT64_C(1) << ISA_CRC32C, + + ISA_fjathplus_msk = UINT64_C(1) << ISA_FJATHPLUS, + ISA_vis3b_msk = UINT64_C(1) << ISA_VIS3B, + ISA_adi_msk = UINT64_C(1) << ISA_ADI, + ISA_sparc5_msk = UINT64_C(1) << ISA_SPARC5, + ISA_mwait_msk = UINT64_C(1) << ISA_MWAIT, + ISA_xmpmul_msk = UINT64_C(1) << ISA_XMPMUL, + ISA_xmont_msk = UINT64_C(1) << ISA_XMONT, + ISA_pause_nsec_msk = UINT64_C(1) << ISA_PAUSE_NSEC, + ISA_vamask_msk = UINT64_C(1) << ISA_VAMASK, + + CPU_fast_idiv_msk = UINT64_C(1) << CPU_FAST_IDIV, + CPU_fast_rdpc_msk = UINT64_C(1) << CPU_FAST_RDPC, + CPU_fast_bis_msk = UINT64_C(1) << CPU_FAST_BIS, + CPU_fast_ld_msk = UINT64_C(1) << CPU_FAST_LD, + CPU_fast_cmove_msk = UINT64_C(1) << CPU_FAST_CMOVE, + CPU_fast_ind_br_msk = UINT64_C(1) << CPU_FAST_IND_BR, + CPU_blk_zeroing_msk = UINT64_C(1) << CPU_BLK_ZEROING, + + last_feature_msk = CPU_blk_zeroing_msk, + full_feature_msk = (last_feature_msk << 1) - 1 }; - static unsigned int _L2_data_cache_line_size; - static unsigned int L2_data_cache_line_size() { return _L2_data_cache_line_size; } +/* The following, previously supported, SPARC implementations are no longer + * supported. + * + * UltraSPARC I/II: + * SPARC-V9, VIS + * UltraSPARC III/+: (Cheetah/+) + * SPARC-V9, VIS + * UltraSPARC IV: (Jaguar) + * SPARC-V9, VIS + * UltraSPARC IV+: (Panther) + * SPARC-V9, VIS, POPC + * + * The currently supported SPARC implementations are listed below (including + * generic V9 support). + * + * UltraSPARC T1: (Niagara) + * SPARC-V9, VIS, ASI_BIS (Crypto/hash in SPU) + * UltraSPARC T2: (Niagara-2) + * SPARC-V9, VIS, ASI_BIS, POPC (Crypto/hash in SPU) + * UltraSPARC T2+: (Victoria Falls, etc.) + * SPARC-V9, VIS, VIS2, ASI_BIS, POPC (Crypto/hash in SPU) + * + * UltraSPARC T3: (Rainbow Falls/S2) + * SPARC-V9, VIS, VIS2, ASI_BIS, POPC (Crypto/hash in SPU) + * + * Oracle SPARC T4/T5/M5: (Core S3) + * SPARC-V9, VIS, VIS2, VIS3, ASI_BIS, HPC, POPC, FMAF, IMA, PAUSE, CBCOND, + * AES, DES, Kasumi, Camellia, MD5, SHA1, SHA256, SHA512, CRC32C, MONT, MPMUL + * + * Oracle SPARC M7: (Core S4) + * SPARC-V9, VIS, VIS2, VIS3, ASI_BIS, HPC, POPC, FMAF, IMA, PAUSE, CBCOND, + * AES, DES, Camellia, MD5, SHA1, SHA256, SHA512, CRC32C, MONT, MPMUL, VIS3b, + * ADI, SPARC5, MWAIT, XMPMUL, XMONT, PAUSE_NSEC, VAMASK + * + */ + enum { + niagara1_msk = ISA_v9_msk | ISA_vis1_msk | ISA_blk_init_msk, + niagara2_msk = niagara1_msk | ISA_popc_msk, + core_S2_msk = niagara2_msk | ISA_vis2_msk, + + core_S3_msk = core_S2_msk | ISA_fmaf_msk | ISA_vis3_msk | ISA_hpc_msk | + ISA_ima_msk | ISA_aes_msk | ISA_des_msk | ISA_kasumi_msk | + ISA_camellia_msk | ISA_md5_msk | ISA_sha1_msk | ISA_sha256_msk | + ISA_sha512_msk | ISA_mpmul_msk | ISA_mont_msk | ISA_pause_msk | + ISA_cbcond_msk | ISA_crc32c_msk, + + core_S4_msk = core_S3_msk - ISA_kasumi_msk | + ISA_vis3b_msk | ISA_adi_msk | ISA_sparc5_msk | ISA_mwait_msk | + ISA_xmpmul_msk | ISA_xmont_msk | ISA_pause_nsec_msk | ISA_vamask_msk, + + ultra_sparc_t1_msk = niagara1_msk, + ultra_sparc_t2_msk = niagara2_msk, + ultra_sparc_t3_msk = core_S2_msk, + ultra_sparc_m5_msk = core_S3_msk, // NOTE: First out-of-order pipeline. + ultra_sparc_m7_msk = core_S4_msk + }; + + static uint _L2_data_cache_line_size; + static uint L2_data_cache_line_size() { return _L2_data_cache_line_size; } + + static void determine_features(); + static void platform_features(); static void print_features(); - static int determine_features(); - static int platform_features(int features); - // Returns true if the platform is in the niagara line (T series) - static bool is_M_family(int features) { return (features & M_family_m) != 0; } - static bool is_S_family(int features) { return (features & S_family_m) != 0; } - static bool is_T_family(int features) { return (features & T_family_m) != 0; } - static bool is_niagara() { return is_T_family(_features); } -#ifdef ASSERT - static bool is_niagara(int features) { - // 'sun4v_m' may be defined on both Sun/Oracle Sparc CPUs as well as - // on Fujitsu Sparc64 CPUs, but only Sun/Oracle Sparcs can be 'niagaras'. - return (features & sun4v_m) != 0 && (features & sparc64_family_m) == 0; - } -#endif - - // Returns true if it is niagara1 (T1). - static bool is_T1_model(int features) { return is_T_family(features) && ((features & T1_model_m) != 0); } - - static int maximum_niagara1_processor_count() { return 32; } - static int parse_features(const char* implementation); public: - // Initialization + enum { + // Adopt a conservative behaviour (modelling single-insn-fetch-n-issue) for + // Niagara (and SPARC64). While there are at least two entries/slots in the + // instruction fetch buffer on any Niagara core (and as many as eight on a + // SPARC64), the performance improvement from keeping hot branch targets on + // optimally aligned addresses is such a small one (if any) that we choose + // not to use the extra code space required. + + insn_fetch_alignment = 4 // Byte alignment in L1 insn. cache. + }; + static void initialize(); - static void init_before_ergo() { _features = determine_features(); } + static void init_before_ergo() { determine_features(); } - // Instruction support - static bool has_v8() { return (_features & v8_instructions_m) != 0; } - static bool has_v9() { return (_features & v9_instructions_m) != 0; } - static bool has_hardware_mul32() { return (_features & hardware_mul32_m) != 0; } - static bool has_hardware_div32() { return (_features & hardware_div32_m) != 0; } - static bool has_hardware_fsmuld() { return (_features & hardware_fsmuld_m) != 0; } - static bool has_hardware_popc() { return (_features & hardware_popc_m) != 0; } - static bool has_vis1() { return (_features & vis1_instructions_m) != 0; } - static bool has_vis2() { return (_features & vis2_instructions_m) != 0; } - static bool has_vis3() { return (_features & vis3_instructions_m) != 0; } - static bool has_blk_init() { return (_features & blk_init_instructions_m) != 0; } - static bool has_cbcond() { return (_features & cbcond_instructions_m) != 0; } - static bool has_sparc5_instr() { return (_features & sparc5_instructions_m) != 0; } - static bool has_aes() { return (_features & aes_instructions_m) != 0; } - static bool has_sha1() { return (_features & sha1_instruction_m) != 0; } - static bool has_sha256() { return (_features & sha256_instruction_m) != 0; } - static bool has_sha512() { return (_features & sha512_instruction_m) != 0; } - static bool has_crc32c() { return (_features & crc32c_instruction_m) != 0; } + // Instruction feature support: - static bool supports_compare_and_exchange() - { return has_v9(); } + static bool has_v9() { return (_features & ISA_v9_msk) != 0; } + static bool has_popc() { return (_features & ISA_popc_msk) != 0; } + static bool has_vis1() { return (_features & ISA_vis1_msk) != 0; } + static bool has_vis2() { return (_features & ISA_vis2_msk) != 0; } + static bool has_blk_init() { return (_features & ISA_blk_init_msk) != 0; } + static bool has_fmaf() { return (_features & ISA_fmaf_msk) != 0; } + static bool has_vis3() { return (_features & ISA_vis3_msk) != 0; } + static bool has_hpc() { return (_features & ISA_hpc_msk) != 0; } + static bool has_ima() { return (_features & ISA_ima_msk) != 0; } + static bool has_aes() { return (_features & ISA_aes_msk) != 0; } + static bool has_des() { return (_features & ISA_des_msk) != 0; } + static bool has_kasumi() { return (_features & ISA_kasumi_msk) != 0; } + static bool has_camellia() { return (_features & ISA_camellia_msk) != 0; } + static bool has_md5() { return (_features & ISA_md5_msk) != 0; } + static bool has_sha1() { return (_features & ISA_sha1_msk) != 0; } + static bool has_sha256() { return (_features & ISA_sha256_msk) != 0; } + static bool has_sha512() { return (_features & ISA_sha512_msk) != 0; } + static bool has_mpmul() { return (_features & ISA_mpmul_msk) != 0; } + static bool has_mont() { return (_features & ISA_mont_msk) != 0; } + static bool has_pause() { return (_features & ISA_pause_msk) != 0; } + static bool has_cbcond() { return (_features & ISA_cbcond_msk) != 0; } + static bool has_crc32c() { return (_features & ISA_crc32c_msk) != 0; } - // Returns true if the platform is in the niagara line (T series) - // and newer than the niagara1. - static bool is_niagara_plus() { return is_T_family(_features) && !is_T1_model(_features); } + static bool has_athena_plus() { return (_features & ISA_fjathplus_msk) != 0; } + static bool has_vis3b() { return (_features & ISA_vis3b_msk) != 0; } + static bool has_adi() { return (_features & ISA_adi_msk) != 0; } + static bool has_sparc5() { return (_features & ISA_sparc5_msk) != 0; } + static bool has_mwait() { return (_features & ISA_mwait_msk) != 0; } + static bool has_xmpmul() { return (_features & ISA_xmpmul_msk) != 0; } + static bool has_xmont() { return (_features & ISA_xmont_msk) != 0; } + static bool has_pause_nsec() { return (_features & ISA_pause_nsec_msk) != 0; } + static bool has_vamask() { return (_features & ISA_vamask_msk) != 0; } - static bool is_M_series() { return is_M_family(_features); } - static bool is_S_series() { return is_S_family(_features); } - static bool is_T4() { return is_T_family(_features) && has_cbcond(); } - static bool is_T7() { return is_T_family(_features) && has_sparc5_instr(); } + static bool has_fast_idiv() { return (_features & CPU_fast_idiv_msk) != 0; } + static bool has_fast_rdpc() { return (_features & CPU_fast_rdpc_msk) != 0; } + static bool has_fast_bis() { return (_features & CPU_fast_bis_msk) != 0; } + static bool has_fast_ld() { return (_features & CPU_fast_ld_msk) != 0; } + static bool has_fast_cmove() { return (_features & CPU_fast_cmove_msk) != 0; } - // Fujitsu SPARC64 - static bool is_sparc64() { return (_features & sparc64_family_m) != 0; } + // If indirect and direct branching is equally fast. + static bool has_fast_ind_br() { return (_features & CPU_fast_ind_br_msk) != 0; } + // If SPARC BIS to the beginning of cache line always zeros it. + static bool has_blk_zeroing() { return (_features & CPU_blk_zeroing_msk) != 0; } - static bool is_sun4v() { return (_features & sun4v_m) != 0; } - static bool is_ultra3() { return (_features & ultra3_m) == ultra3_m && !is_sun4v() && !is_sparc64(); } + static bool supports_compare_and_exchange() { return true; } - static bool has_fast_fxtof() { return is_niagara() || is_sparc64() || has_v9() && !is_ultra3(); } - static bool has_fast_idiv() { return is_niagara_plus() || is_sparc64(); } + // FIXME: To be removed. + static bool is_post_niagara() { + return (_features & niagara2_msk) == niagara2_msk; + } - // T4 and newer Sparc have fast RDPC instruction. - static bool has_fast_rdpc() { return is_T4(); } + // Default prefetch block size on SPARC. + static uint prefetch_data_size() { return L2_data_cache_line_size(); } - // On T4 and newer Sparc BIS to the beginning of cache line always zeros it. - static bool has_block_zeroing() { return has_blk_init() && is_T4(); } - - // default prefetch block size on sparc - static intx prefetch_data_size() { return L2_data_cache_line_size(); } - - // Prefetch + private: + // Prefetch policy and characteristics: + // + // These support routines are used in order to isolate any CPU/core specific + // logic from the actual flag/option processing. They should reflect the HW + // characteristics for the associated options on the current platform. + // + // The three Prefetch* options below (assigned -1 in the configuration) are + // treated according to (given the accepted range [-1..]): + // -1: Determine a proper HW-specific value for the current HW. + // 0: Off + // >0: Command-line supplied value to use. + // + // FIXME: The documentation string in the configuration is wrong, saying that + // -1 is also interpreted as off. + // static intx prefetch_copy_interval_in_bytes() { - intx interval = PrefetchCopyIntervalInBytes; - return interval >= 0 ? interval : (has_v9() ? 512 : 0); + intx bytes = PrefetchCopyIntervalInBytes; + return bytes < 0 ? 512 : bytes; } static intx prefetch_scan_interval_in_bytes() { - intx interval = PrefetchScanIntervalInBytes; - return interval >= 0 ? interval : (has_v9() ? 512 : 0); + intx bytes = PrefetchScanIntervalInBytes; + return bytes < 0 ? 512 : bytes; } static intx prefetch_fields_ahead() { intx count = PrefetchFieldsAhead; - return count >= 0 ? count : (is_ultra3() ? 1 : 0); + return count < 0 ? 0 : count; } + // AllocatePrefetchDistance is treated under the same interpretation as the + // Prefetch* options above (i.e., -1, 0, >0). static intx allocate_prefetch_distance() { - // This method should be called before allocate_prefetch_style(). intx count = AllocatePrefetchDistance; - if (count < 0) { // default is not defined ? - count = 512; - } - return count; - } - static intx allocate_prefetch_style() { - assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); - // Return 0 if AllocatePrefetchDistance was not defined. - return AllocatePrefetchDistance > 0 ? AllocatePrefetchStyle : 0; + return count < 0 ? 512 : count; } + // AllocatePrefetchStyle is guaranteed to be in range [0..3] defined by the + // configuration. + static intx allocate_prefetch_style() { + intx distance = allocate_prefetch_distance(); + // Return 0 (off/none) if AllocatePrefetchDistance was not defined. + return distance > 0 ? AllocatePrefetchStyle : 0; + } + + public: // Assembler testing static void allow_all(); static void revert(); // Override the Abstract_VM_Version implementation. - static uint page_size_count() { return is_sun4v() ? 4 : 2; } + // + // FIXME: Removed broken test on sun4v (always false when invoked prior to the + // proper capability setup), thus always returning 2. Still need to fix + // this properly in order to enable complete page size support. + static uint page_size_count() { return 2; } // Calculates the number of parallel threads static unsigned int calc_parallel_worker_threads(); diff --git a/hotspot/src/cpu/sparc/vm/vmreg_sparc.hpp b/hotspot/src/cpu/sparc/vm/vmreg_sparc.hpp index 29f38a8d8ca..e1f4591002d 100644 --- a/hotspot/src/cpu/sparc/vm/vmreg_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/vmreg_sparc.hpp @@ -27,9 +27,8 @@ inline bool is_Register() { return value() >= 0 && value() < ConcreteRegisterImpl::max_gpr; } inline bool is_FloatRegister() { return value() >= ConcreteRegisterImpl::max_gpr && - value() < ConcreteRegisterImpl::max_fpr; } + value() < ConcreteRegisterImpl::max_fpr; } inline Register as_Register() { - assert( is_Register() && is_even(value()), "even-aligned GPR name" ); // Yuk return ::as_Register(value()>>1); diff --git a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp index 9e825aaa79e..3249b3a26f3 100644 --- a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp @@ -232,7 +232,7 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) { MacroAssembler::instr_size_for_decode_klass_not_null() : 0); return basic + slop; } else { - const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord + + const int basic = 34 * BytesPerInstWord + // shift;add for load_klass (only shift with zero heap based) (UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0); @@ -257,7 +257,6 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) { // ld [ %g3 + 0xe8 ], %l2 // sll %l2, 2, %l2 // add %l2, 0x134, %l2 - // and %l2, -8, %l2 ! NOT_LP64 only // add %g3, %l2, %l2 // add %g3, 4, %g3 // ld [ %l2 ], %l5 diff --git a/hotspot/src/cpu/x86/vm/abstractInterpreter_x86.cpp b/hotspot/src/cpu/x86/vm/abstractInterpreter_x86.cpp index 0865b99a0d6..5c146f84d5e 100644 --- a/hotspot/src/cpu/x86/vm/abstractInterpreter_x86.cpp +++ b/hotspot/src/cpu/x86/vm/abstractInterpreter_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -160,27 +160,6 @@ int AbstractInterpreter::BasicType_as_index(BasicType type) { } #endif // _LP64 -// These should never be compiled since the interpreter will prefer -// the compiled version to the intrinsic version. -bool AbstractInterpreter::can_be_compiled(methodHandle m) { - switch (method_kind(m)) { - case Interpreter::java_lang_math_sin : // fall thru - case Interpreter::java_lang_math_cos : // fall thru - case Interpreter::java_lang_math_tan : // fall thru - case Interpreter::java_lang_math_abs : // fall thru - case Interpreter::java_lang_math_log : // fall thru - case Interpreter::java_lang_math_log10 : // fall thru - case Interpreter::java_lang_math_sqrt : // fall thru - case Interpreter::java_lang_math_pow : // fall thru - case Interpreter::java_lang_math_exp : // fall thru - case Interpreter::java_lang_math_fmaD : // fall thru - case Interpreter::java_lang_math_fmaF : - return false; - default: - return true; - } -} - // How much stack a method activation needs in words. int AbstractInterpreter::size_top_interpreter_activation(Method* method) { const int entry_size = frame::interpreter_frame_monitor_size(); diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index 3c6d7b5cdd6..3bdc0ed3c30 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -2103,12 +2103,20 @@ void Assembler::jmpb(Label& L) { } void Assembler::ldmxcsr( Address src) { - NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - prefix(src); - emit_int8(0x0F); - emit_int8((unsigned char)0xAE); - emit_operand(as_Register(2), src); + if (UseAVX > 0 ) { + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + vex_prefix(src, 0, 0, VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes); + emit_int8((unsigned char)0xAE); + emit_operand(as_Register(2), src); + } else { + NOT_LP64(assert(VM_Version::supports_sse(), "")); + InstructionMark im(this); + prefix(src); + emit_int8(0x0F); + emit_int8((unsigned char)0xAE); + emit_operand(as_Register(2), src); + } } void Assembler::leal(Register dst, Address src) { @@ -3313,6 +3321,11 @@ void Assembler::pause() { emit_int8((unsigned char)0x90); } +void Assembler::ud2() { + emit_int8(0x0F); + emit_int8(0x0B); +} + void Assembler::pcmpestri(XMMRegister dst, Address src, int imm8) { assert(VM_Version::supports_sse4_2(), ""); InstructionMark im(this); @@ -4416,12 +4429,21 @@ void Assembler::sqrtss(XMMRegister dst, Address src) { } void Assembler::stmxcsr( Address dst) { - NOT_LP64(assert(VM_Version::supports_sse(), "")); - InstructionMark im(this); - prefix(dst); - emit_int8(0x0F); - emit_int8((unsigned char)0xAE); - emit_operand(as_Register(3), dst); + if (UseAVX > 0 ) { + assert(VM_Version::supports_avx(), ""); + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + vex_prefix(dst, 0, 0, VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes); + emit_int8((unsigned char)0xAE); + emit_operand(as_Register(3), dst); + } else { + NOT_LP64(assert(VM_Version::supports_sse(), "")); + InstructionMark im(this); + prefix(dst); + emit_int8(0x0F); + emit_int8((unsigned char)0xAE); + emit_operand(as_Register(3), dst); + } } void Assembler::subl(Address dst, int32_t imm32) { @@ -5070,6 +5092,42 @@ void Assembler::vmulps(XMMRegister dst, XMMRegister nds, Address src, int vector emit_operand(dst, src); } +void Assembler::vfmadd231pd(XMMRegister dst, XMMRegister src1, XMMRegister src2, int vector_len) { + assert(VM_Version::supports_fma(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + int encode = vex_prefix_and_encode(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xB8); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::vfmadd231ps(XMMRegister dst, XMMRegister src1, XMMRegister src2, int vector_len) { + assert(VM_Version::supports_fma(), ""); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + int encode = vex_prefix_and_encode(dst->encoding(), src1->encoding(), src2->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xB8); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::vfmadd231pd(XMMRegister dst, XMMRegister src1, Address src2, int vector_len) { + assert(VM_Version::supports_fma(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_64bit); + vex_prefix(src2, src1->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xB8); + emit_operand(dst, src2); +} + +void Assembler::vfmadd231ps(XMMRegister dst, XMMRegister src1, Address src2, int vector_len) { + assert(VM_Version::supports_fma(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_32bit); + vex_prefix(src2, src1->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xB8); + emit_operand(dst, src2); +} + void Assembler::divpd(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); @@ -6620,10 +6678,11 @@ void Assembler::vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, in } void Assembler::vzeroupper() { - assert(VM_Version::supports_avx(), ""); - InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); - (void)vex_prefix_and_encode(0, 0, 0, VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes); - emit_int8(0x77); + if (VM_Version::supports_vzeroupper()) { + InstructionAttr attributes(AVX_128bit, /* vex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + (void)vex_prefix_and_encode(0, 0, 0, VEX_SIMD_NONE, VEX_OPCODE_0F, &attributes); + emit_int8(0x77); + } } #ifndef _LP64 diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index ada59ae288c..c4e6645e319 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -1554,6 +1554,9 @@ private: void pause(); + // Undefined Instruction + void ud2(); + // SSE4.2 string instructions void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8); void pcmpestri(XMMRegister xmm1, Address src, int imm8); @@ -1903,6 +1906,11 @@ private: void vmulpd(XMMRegister dst, XMMRegister nds, Address src, int vector_len); void vmulps(XMMRegister dst, XMMRegister nds, Address src, int vector_len); + void vfmadd231pd(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void vfmadd231ps(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void vfmadd231pd(XMMRegister dst, XMMRegister nds, Address src, int vector_len); + void vfmadd231ps(XMMRegister dst, XMMRegister nds, Address src, int vector_len); + // Divide Packed Floating-Point Values void divpd(XMMRegister dst, XMMRegister src); void divps(XMMRegister dst, XMMRegister src); diff --git a/hotspot/src/cpu/x86/vm/bytes_x86.hpp b/hotspot/src/cpu/x86/vm/bytes_x86.hpp index eb5ab17ca08..8636e8810fe 100644 --- a/hotspot/src/cpu/x86/vm/bytes_x86.hpp +++ b/hotspot/src/cpu/x86/vm/bytes_x86.hpp @@ -26,6 +26,7 @@ #define CPU_X86_VM_BYTES_X86_HPP #include "memory/allocation.hpp" +#include "utilities/align.hpp" #include "utilities/macros.hpp" class Bytes: AllStatic { @@ -36,36 +37,85 @@ class Bytes: AllStatic { #endif // AMD64 public: - // Returns true if the byte ordering used by Java is different from the native byte ordering - // of the underlying machine. For example, this is true for Intel x86, but false for Solaris - // on Sparc. - static inline bool is_Java_byte_ordering_different(){ return true; } - - // Efficient reading and writing of unaligned unsigned data in platform-specific byte ordering - // (no special code is needed since x86 CPUs can access unaligned data) - static inline u2 get_native_u2(address p) { return *(u2*)p; } - static inline u4 get_native_u4(address p) { return *(u4*)p; } - static inline u8 get_native_u8(address p) { return *(u8*)p; } + template + static inline T get_native(const void* p) { + assert(p != NULL, "null pointer"); - static inline void put_native_u2(address p, u2 x) { *(u2*)p = x; } - static inline void put_native_u4(address p, u4 x) { *(u4*)p = x; } - static inline void put_native_u8(address p, u8 x) { *(u8*)p = x; } + T x; + if (is_aligned(p, sizeof(T))) { + x = *(T*)p; + } else { + memcpy(&x, p, sizeof(T)); + } + + return x; + } + + template + static inline void put_native(void* p, T x) { + assert(p != NULL, "null pointer"); + + if (is_aligned(p, sizeof(T))) { + *(T*)p = x; + } else { + memcpy(p, &x, sizeof(T)); + } + } + + static inline u2 get_native_u2(address p) { return get_native((void*)p); } + static inline u4 get_native_u4(address p) { return get_native((void*)p); } + static inline u8 get_native_u8(address p) { return get_native((void*)p); } + static inline void put_native_u2(address p, u2 x) { put_native((void*)p, x); } + static inline void put_native_u4(address p, u4 x) { put_native((void*)p, x); } + static inline void put_native_u8(address p, u8 x) { put_native((void*)p, x); } // Efficient reading and writing of unaligned unsigned data in Java // byte ordering (i.e. big-endian ordering). Byte-order reversal is // needed since x86 CPUs use little-endian format. - static inline u2 get_Java_u2(address p) { return swap_u2(get_native_u2(p)); } - static inline u4 get_Java_u4(address p) { return swap_u4(get_native_u4(p)); } - static inline u8 get_Java_u8(address p) { return swap_u8(get_native_u8(p)); } + template + static inline T get_Java(const address p) { + T x = get_native(p); - static inline void put_Java_u2(address p, u2 x) { put_native_u2(p, swap_u2(x)); } - static inline void put_Java_u4(address p, u4 x) { put_native_u4(p, swap_u4(x)); } - static inline void put_Java_u8(address p, u8 x) { put_native_u8(p, swap_u8(x)); } + if (Endian::is_Java_byte_ordering_different()) { + x = swap(x); + } + return x; + } + + template + static inline void put_Java(address p, T x) { + if (Endian::is_Java_byte_ordering_different()) { + x = swap(x); + } + + put_native(p, x); + } + + static inline u2 get_Java_u2(address p) { return get_Java(p); } + static inline u4 get_Java_u4(address p) { return get_Java(p); } + static inline u8 get_Java_u8(address p) { return get_Java(p); } + + static inline void put_Java_u2(address p, u2 x) { put_Java(p, x); } + static inline void put_Java_u4(address p, u4 x) { put_Java(p, x); } + static inline void put_Java_u8(address p, u8 x) { put_Java(p, x); } // Efficient swapping of byte ordering + template + static T swap(T x) { + switch (sizeof(T)) { + case sizeof(u1): return x; + case sizeof(u2): return swap_u2(x); + case sizeof(u4): return swap_u4(x); + case sizeof(u8): return swap_u8(x); + default: + guarantee(false, "invalid size: " SIZE_FORMAT "\n", sizeof(T)); + return 0; + } + } + static inline u2 swap_u2(u2 x); // compiler-dependent implementation static inline u4 swap_u4(u4 x); // compiler-dependent implementation static inline u8 swap_u8(u8 x); diff --git a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp index 4f6690fa540..79ab7ddbf33 100644 --- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp @@ -30,6 +30,7 @@ #include "c1/c1_Runtime1.hpp" #include "nativeInst_x86.hpp" #include "runtime/sharedRuntime.hpp" +#include "utilities/align.hpp" #include "utilities/macros.hpp" #include "vmreg_x86.inline.hpp" #if INCLUDE_ALL_GCS @@ -290,7 +291,7 @@ void PatchingStub::align_patch_site(MacroAssembler* masm) { // very hard to make a guess about what code might be in the icache. // Force the instruction to be double word aligned so that it // doesn't span a cache line. - masm->align(round_to(NativeGeneralJump::instruction_size, wordSize)); + masm->align(align_up((int)NativeGeneralJump::instruction_size, wordSize)); } void PatchingStub::emit_code(LIR_Assembler* ce) { diff --git a/hotspot/src/cpu/x86/vm/c1_FpuStackSim_x86.cpp b/hotspot/src/cpu/x86/vm/c1_FpuStackSim_x86.cpp index 6d91d1948e9..3ec182a350b 100644 --- a/hotspot/src/cpu/x86/vm/c1_FpuStackSim_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_FpuStackSim_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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,7 +25,7 @@ #include "precompiled.hpp" #include "c1/c1_FpuStackSim.hpp" #include "c1/c1_FrameMap.hpp" -#include "utilities/array.hpp" +#include "utilities/growableArray.hpp" #include "utilities/ostream.hpp" //-------------------------------------------------------- diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 8aa4aec76b6..f747e41e522 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -1160,6 +1160,8 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch __ xorptr(dest->as_register(), dest->as_register()); } break; + default: + break; } PatchingStub* patch = NULL; diff --git a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp index 95ee2d54beb..6995986e4d4 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -649,8 +649,8 @@ void LIRGenerator::do_ArithmeticOp(ArithmeticOp* x) { case doubleTag: do_ArithmeticOp_FPU(x); return; case longTag: do_ArithmeticOp_Long(x); return; case intTag: do_ArithmeticOp_Int(x); return; + default: ShouldNotReachHere(); return; } - ShouldNotReachHere(); } diff --git a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp index e291000eab0..54a0c569219 100644 --- a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -826,6 +826,9 @@ void FpuStackAllocator::check_invalid_lir_op(LIR_Op* op) { case lir_fld: assert(false, "operations only inserted by FpuStackAllocator"); break; + + default: + break; } } #endif diff --git a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp index 6d0dbb8756d..a1044b6b2a2 100644 --- a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -92,6 +92,8 @@ inline void LinearScan::pd_add_temps(LIR_Op* op) { } break; } + default: + break; } } diff --git a/hotspot/src/cpu/x86/vm/compiledIC_aot_x86_64.cpp b/hotspot/src/cpu/x86/vm/compiledIC_aot_x86_64.cpp index 6b711506fab..d884ef2a87c 100644 --- a/hotspot/src/cpu/x86/vm/compiledIC_aot_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/compiledIC_aot_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -21,6 +21,8 @@ * questions. */ +#include "precompiled.hpp" + #include "aot/compiledIC_aot.hpp" #include "code/codeCache.hpp" #include "memory/resourceArea.hpp" diff --git a/hotspot/src/cpu/x86/vm/debug_x86.cpp b/hotspot/src/cpu/x86/vm/debug_x86.cpp deleted file mode 100644 index 0bde483a789..00000000000 --- a/hotspot/src/cpu/x86/vm/debug_x86.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 1999, 2010, 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 "code/codeCache.hpp" -#include "code/nmethod.hpp" -#include "runtime/frame.hpp" -#include "runtime/init.hpp" -#include "runtime/os.hpp" -#include "utilities/debug.hpp" - -void pd_ps(frame f) {} diff --git a/hotspot/src/cpu/x86/vm/frame_x86.cpp b/hotspot/src/cpu/x86/vm/frame_x86.cpp index 11f28bdb6ca..a64ceb2a2ed 100644 --- a/hotspot/src/cpu/x86/vm/frame_x86.cpp +++ b/hotspot/src/cpu/x86/vm/frame_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -680,6 +680,8 @@ intptr_t* frame::real_fp() const { frame::frame(void* sp, void* fp, void* pc) { init((intptr_t*)sp, (intptr_t*)fp, (address)pc); } + +void frame::pd_ps() {} #endif void JavaFrameAnchor::make_walkable(JavaThread* thread) { diff --git a/hotspot/src/cpu/x86/vm/globals_x86.hpp b/hotspot/src/cpu/x86/vm/globals_x86.hpp index 748a1af0326..80344a3c8cf 100644 --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -116,7 +116,7 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); product(bool, UseStoreImmI16, true, \ "Use store immediate 16-bits value instruction on x86") \ \ - product(intx, UseAVX, 2, \ + product(intx, UseAVX, 3, \ "Highest supported AVX instructions set on x86/x64") \ range(0, 99) \ \ @@ -160,25 +160,31 @@ define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); product(bool, UseRTMDeopt, false, \ "Perform deopt and recompilation based on RTM abort ratio") \ \ - product(uintx, RTMRetryCount, 5, \ + product(int, RTMRetryCount, 5, \ "Number of RTM retries on lock abort or busy") \ - range(0, max_uintx) \ + range(0, max_jint) \ \ - experimental(intx, RTMSpinLoopCount, 100, \ + experimental(int, RTMSpinLoopCount, 100, \ "Spin count for lock to become free before RTM retry") \ + range(0, max_jint) \ \ - experimental(intx, RTMAbortThreshold, 1000, \ + experimental(int, RTMAbortThreshold, 1000, \ "Calculate abort ratio after this number of aborts") \ + range(0, max_jint) \ \ - experimental(intx, RTMLockingThreshold, 10000, \ + experimental(int, RTMLockingThreshold, 10000, \ "Lock count at which to do RTM lock eliding without " \ "abort ratio calculation") \ + range(0, max_jint) \ \ - experimental(intx, RTMAbortRatio, 50, \ + experimental(int, RTMAbortRatio, 50, \ "Lock abort ratio at which to stop use RTM lock eliding") \ + range(0, 100) /* natural range */ \ \ - experimental(intx, RTMTotalCountIncrRate, 64, \ + experimental(int, RTMTotalCountIncrRate, 64, \ "Increment total RTM attempted lock count once every n times") \ + range(1, max_jint) \ + constraint(RTMTotalCountIncrRateConstraintFunc,AfterErgo) \ \ experimental(intx, RTMLockingCalculationDelay, 0, \ "Number of milliseconds to wait before start calculating aborts " \ diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp index 331ac5d3405..6d27ee79a0a 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -509,7 +509,8 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( get_constant_pool(result); // load pointer for resolved_references[] objArray - movptr(result, Address(result, ConstantPool::resolved_references_offset_in_bytes())); + movptr(result, Address(result, ConstantPool::cache_offset_in_bytes())); + movptr(result, Address(result, ConstantPoolCache::resolved_references_offset_in_bytes())); // JNIHandles::resolve(obj); movptr(result, Address(result, 0)); // Add in the index @@ -517,6 +518,14 @@ void InterpreterMacroAssembler::load_resolved_reference_at_index( load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT))); } +// load cpool->resolved_klass_at(index) +void InterpreterMacroAssembler::load_resolved_klass_at_index(Register cpool, + Register index, Register klass) { + movw(index, Address(cpool, index, Address::times_ptr, sizeof(ConstantPool))); + Register resolved_klasses = cpool; + movptr(resolved_klasses, Address(cpool, ConstantPool::resolved_klasses_offset_in_bytes())); + movptr(klass, Address(resolved_klasses, index, Address::times_ptr, Array::base_offset_in_bytes())); +} // Generate a subtype check: branch to ok_is_subtype if sub_klass is a // subtype of super_klass. @@ -1080,7 +1089,6 @@ void InterpreterMacroAssembler::remove_activation( call_VM_leaf( CAST_FROM_FN_PTR(address, SharedRuntime::enable_stack_reserved_zone), rthread); - push(rthread); call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_delayed_StackOverflowError)); should_not_reach_here(); @@ -1148,7 +1156,7 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) { movl(swap_reg, (int32_t)1); // Load (object->mark() | 1) into swap_reg %rax - orptr(swap_reg, Address(obj_reg, 0)); + orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); // Save (object->mark() | 1) into BasicLock's displaced header movptr(Address(lock_reg, mark_offset), swap_reg); @@ -1157,7 +1165,7 @@ void InterpreterMacroAssembler::lock_object(Register lock_reg) { "displaced header must be first word in BasicObjectLock"); if (os::is_MP()) lock(); - cmpxchgptr(lock_reg, Address(obj_reg, 0)); + cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); if (PrintBiasedLockingStatistics) { cond_inc32(Assembler::zero, ExternalAddress((address) BiasedLocking::fast_path_entry_count_addr())); @@ -1254,7 +1262,7 @@ void InterpreterMacroAssembler::unlock_object(Register lock_reg) { // Atomic swap back the old header if (os::is_MP()) lock(); - cmpxchgptr(header_reg, Address(obj_reg, 0)); + cmpxchgptr(header_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); // zero for simple unlock of a stack-lock case jcc(Assembler::zero, done); diff --git a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp index 9ed5c2c9ad3..0095564c1b0 100644 --- a/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp +++ b/hotspot/src/cpu/x86/vm/interp_masm_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -48,9 +48,6 @@ class InterpreterMacroAssembler: public MacroAssembler { int number_of_arguments, bool check_exceptions); - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - // base routine for all dispatches void dispatch_base(TosState state, address* table, bool verifyoop = true); @@ -61,6 +58,9 @@ class InterpreterMacroAssembler: public MacroAssembler { void jump_to_entry(address entry); + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + void load_earlyret_value(TosState state); // Interpreter-specific registers @@ -123,6 +123,11 @@ class InterpreterMacroAssembler: public MacroAssembler { // load cpool->resolved_references(index); void load_resolved_reference_at_index(Register result, Register index); + // load cpool->resolved_klass_at(index) + void load_resolved_klass_at_index(Register cpool, // the constant pool (corrupted on return) + Register index, // the constant pool index (corrupted on return) + Register klass); // contains the Klass on return + NOT_LP64(void f2ieee();) // truncate ftos to 32bits NOT_LP64(void d2ieee();) // truncate dtos to 64bits diff --git a/hotspot/src/cpu/x86/vm/interpreterRT_x86.hpp b/hotspot/src/cpu/x86/vm/interpreterRT_x86.hpp index f35f0122d43..dd0aa20d426 100644 --- a/hotspot/src/cpu/x86/vm/interpreterRT_x86.hpp +++ b/hotspot/src/cpu/x86/vm/interpreterRT_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -55,7 +55,7 @@ class SignatureHandlerGenerator: public NativeSignatureIterator { public: // Creation - SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) : NativeSignatureIterator(method) { + SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer) : NativeSignatureIterator(method) { _masm = new MacroAssembler(buffer); #ifdef AMD64 #ifdef _WIN64 diff --git a/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp b/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp index 0e68dd011d3..18d57924912 100644 --- a/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/interpreterRT_x86_32.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2017, 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 @@ -124,7 +124,7 @@ class SlowSignatureHandler: public NativeSignatureIterator { } public: - SlowSignatureHandler(methodHandle method, address from, intptr_t* to) : + SlowSignatureHandler(const methodHandle& method, address from, intptr_t* to) : NativeSignatureIterator(method) { _from = from; _to = to + (is_static() ? 2 : 1); diff --git a/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp b/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp index 40cc9d71aa7..53f03a38b6c 100644 --- a/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/interpreterRT_x86_64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -369,7 +369,7 @@ class SlowSignatureHandler } public: - SlowSignatureHandler(methodHandle method, address from, intptr_t* to) + SlowSignatureHandler(const methodHandle& method, address from, intptr_t* to) : NativeSignatureIterator(method) { _from = from; @@ -461,7 +461,7 @@ class SlowSignatureHandler } public: - SlowSignatureHandler(methodHandle method, address from, intptr_t* to) + SlowSignatureHandler(const methodHandle& method, address from, intptr_t* to) : NativeSignatureIterator(method) { _from = from; diff --git a/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp b/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp index f18aa684266..b078bcf2db3 100644 --- a/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/jniFastGetField_x86_64.cpp @@ -121,7 +121,8 @@ address JNI_FastGetField::generate_fast_get_int_field0(BasicType type) { case T_CHAR: slow_case_addr = jni_GetCharField_addr(); break; case T_SHORT: slow_case_addr = jni_GetShortField_addr(); break; case T_INT: slow_case_addr = jni_GetIntField_addr(); break; - case T_LONG: slow_case_addr = jni_GetLongField_addr(); + case T_LONG: slow_case_addr = jni_GetLongField_addr(); break; + default: break; } // tail call __ jump (ExternalAddress(slow_case_addr)); @@ -215,7 +216,8 @@ address JNI_FastGetField::generate_fast_get_float_field0(BasicType type) { address slow_case_addr = NULL; switch (type) { case T_FLOAT: slow_case_addr = jni_GetFloatField_addr(); break; - case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); + case T_DOUBLE: slow_case_addr = jni_GetDoubleField_addr(); break; + default: break; } // tail call __ jump (ExternalAddress(slow_case_addr)); diff --git a/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp b/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp index e2ddb71aa9d..acb7034684e 100644 --- a/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp +++ b/hotspot/src/cpu/x86/vm/jvmciCodeInstaller_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -65,7 +65,7 @@ jint CodeInstaller::pd_next_offset(NativeInstruction* inst, jint pc_offset, Hand void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle constant, TRAPS) { address pc = _instructions->start() + pc_offset; - Handle obj = HotSpotObjectConstantImpl::object(constant); + Handle obj(THREAD, HotSpotObjectConstantImpl::object(constant)); jobject value = JNIHandles::make_local(obj()); if (HotSpotObjectConstantImpl::compressed(constant)) { #ifdef _LP64 diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index 6b7f947de6b..bf1943fcae9 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -32,6 +32,7 @@ #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/klass.inline.hpp" +#include "prims/jvm.h" #include "prims/methodHandles.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/interfaceSupport.hpp" @@ -763,11 +764,13 @@ void MacroAssembler::reset_last_Java_frame(bool clear_fp) { // Always clear the pc because it could have been set by make_walkable() movptr(Address(r15_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); + vzeroupper(); } void MacroAssembler::set_last_Java_frame(Register last_java_sp, Register last_java_fp, address last_java_pc) { + vzeroupper(); // determine last_java_sp register if (!last_java_sp->is_valid()) { last_java_sp = rsp; @@ -891,7 +894,7 @@ void MacroAssembler::debug64(char* msg, int64_t pc, int64_t regs[]) { void MacroAssembler::print_state64(int64_t pc, int64_t regs[]) { ttyLocker ttyl; FlagSetting fs(Debugging, true); - tty->print_cr("rip = 0x%016lx", pc); + tty->print_cr("rip = 0x%016lx", (intptr_t)pc); #ifndef PRODUCT tty->cr(); findpc(pc); @@ -920,13 +923,13 @@ void MacroAssembler::print_state64(int64_t pc, int64_t regs[]) { int64_t* rsp = (int64_t*) regs[11]; int64_t* dump_sp = rsp; for (int col1 = 0; col1 < 8; col1++) { - tty->print("(rsp+0x%03x) 0x%016lx: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (int64_t)dump_sp); + tty->print("(rsp+0x%03x) 0x%016lx: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (intptr_t)dump_sp); os::print_location(tty, *dump_sp++); } for (int row = 0; row < 25; row++) { - tty->print("(rsp+0x%03x) 0x%016lx: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (int64_t)dump_sp); + tty->print("(rsp+0x%03x) 0x%016lx: ", (int)((intptr_t)dump_sp - (intptr_t)rsp), (intptr_t)dump_sp); for (int col = 0; col < 4; col++) { - tty->print(" 0x%016lx", *dump_sp++); + tty->print(" 0x%016lx", (intptr_t)*dump_sp++); } tty->cr(); } @@ -1482,7 +1485,7 @@ void MacroAssembler::rtm_stack_locking(Register objReg, Register tmpReg, Registe movl(retry_on_abort_count_Reg, RTMRetryCount); // Retry on abort bind(L_rtm_retry); } - movptr(tmpReg, Address(objReg, 0)); + movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased jcc(Assembler::notZero, IsInflated); @@ -1490,14 +1493,14 @@ void MacroAssembler::rtm_stack_locking(Register objReg, Register tmpReg, Registe Label L_noincrement; if (RTMTotalCountIncrRate > 1) { // tmpReg, scrReg and flags are killed - branch_on_random_using_rdtsc(tmpReg, scrReg, (int)RTMTotalCountIncrRate, L_noincrement); + branch_on_random_using_rdtsc(tmpReg, scrReg, RTMTotalCountIncrRate, L_noincrement); } assert(stack_rtm_counters != NULL, "should not be NULL when profiling RTM"); atomic_incptr(ExternalAddress((address)stack_rtm_counters->total_count_addr()), scrReg); bind(L_noincrement); } xbegin(L_on_abort); - movptr(tmpReg, Address(objReg, 0)); // fetch markword + movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // fetch markword andptr(tmpReg, markOopDesc::biased_lock_mask_in_place); // look at 3 lock bits cmpptr(tmpReg, markOopDesc::unlocked_value); // bits = 001 unlocked jcc(Assembler::equal, DONE_LABEL); // all done if unlocked @@ -1551,14 +1554,14 @@ void MacroAssembler::rtm_inflated_locking(Register objReg, Register boxReg, Regi Label L_noincrement; if (RTMTotalCountIncrRate > 1) { // tmpReg, scrReg and flags are killed - branch_on_random_using_rdtsc(tmpReg, scrReg, (int)RTMTotalCountIncrRate, L_noincrement); + branch_on_random_using_rdtsc(tmpReg, scrReg, RTMTotalCountIncrRate, L_noincrement); } assert(rtm_counters != NULL, "should not be NULL when profiling RTM"); atomic_incptr(ExternalAddress((address)rtm_counters->total_count_addr()), scrReg); bind(L_noincrement); } xbegin(L_on_abort); - movptr(tmpReg, Address(objReg, 0)); + movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); movptr(tmpReg, Address(tmpReg, owner_offset)); testptr(tmpReg, tmpReg); jcc(Assembler::zero, DONE_LABEL); @@ -1751,7 +1754,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg } #endif // INCLUDE_RTM_OPT - movptr(tmpReg, Address(objReg, 0)); // [FETCH] + movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // [FETCH] testptr(tmpReg, markOopDesc::monitor_value); // inflated vs stack-locked|neutral|biased jccb(Assembler::notZero, IsInflated); @@ -1761,7 +1764,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg if (os::is_MP()) { lock(); } - cmpxchgptr(boxReg, Address(objReg, 0)); // Updates tmpReg + cmpxchgptr(boxReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Updates tmpReg if (counters != NULL) { cond_inc32(Assembler::equal, ExternalAddress((address)counters->fast_path_entry_count_addr())); @@ -1982,7 +1985,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR if (UseRTMForStackLocks && use_rtm) { assert(!UseBiasedLocking, "Biased locking is not supported with RTM locking"); Label L_regular_unlock; - movptr(tmpReg, Address(objReg, 0)); // fetch markword + movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // fetch markword andptr(tmpReg, markOopDesc::biased_lock_mask_in_place); // look at 3 lock bits cmpptr(tmpReg, markOopDesc::unlocked_value); // bits = 001 unlocked jccb(Assembler::notEqual, L_regular_unlock); // if !HLE RegularLock @@ -1994,7 +1997,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR cmpptr(Address(boxReg, 0), (int32_t)NULL_WORD); // Examine the displaced header jcc (Assembler::zero, DONE_LABEL); // 0 indicates recursive stack-lock - movptr(tmpReg, Address(objReg, 0)); // Examine the object's markword + movptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Examine the object's markword testptr(tmpReg, markOopDesc::monitor_value); // Inflated? jccb (Assembler::zero, Stacked); @@ -2148,7 +2151,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR if (os::is_MP()) { lock(); } - cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box + cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box // Intention fall-thru into DONE_LABEL // DONE_LABEL is a hot target - we'd really like to place it at the @@ -2245,7 +2248,7 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR bind (Stacked); movptr(tmpReg, Address (boxReg, 0)); // re-fetch if (os::is_MP()) { lock(); } - cmpxchgptr(tmpReg, Address(objReg, 0)); // Uses RAX which is box + cmpxchgptr(tmpReg, Address(objReg, oopDesc::mark_offset_in_bytes())); // Uses RAX which is box if (EmitSync & 65536) { bind (CheckSucc); @@ -3163,8 +3166,37 @@ void MacroAssembler::fmaf(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegi } } +// dst = c = a * b + c +void MacroAssembler::vfmad(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c, int vector_len) { + Assembler::vfmadd231pd(c, a, b, vector_len); + if (dst != c) { + vmovdqu(dst, c); + } +} +// dst = c = a * b + c +void MacroAssembler::vfmaf(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c, int vector_len) { + Assembler::vfmadd231ps(c, a, b, vector_len); + if (dst != c) { + vmovdqu(dst, c); + } +} +// dst = c = a * b + c +void MacroAssembler::vfmad(XMMRegister dst, XMMRegister a, Address b, XMMRegister c, int vector_len) { + Assembler::vfmadd231pd(c, a, b, vector_len); + if (dst != c) { + vmovdqu(dst, c); + } +} + +// dst = c = a * b + c +void MacroAssembler::vfmaf(XMMRegister dst, XMMRegister a, Address b, XMMRegister c, int vector_len) { + Assembler::vfmadd231ps(c, a, b, vector_len); + if (dst != c) { + vmovdqu(dst, c); + } +} void MacroAssembler::incrementl(AddressLiteral dst) { if (reachable(dst)) { @@ -3609,6 +3641,12 @@ void MacroAssembler::os_breakpoint() { call(RuntimeAddress(CAST_FROM_FN_PTR(address, os::breakpoint))); } +void MacroAssembler::unimplemented(const char* what) { + char* b = new char[1024]; + jio_snprintf(b, 1024, "unimplemented: %s", what); + stop(b); +} + #ifdef _LP64 #define XSTATE_BV 0x200 #endif @@ -3672,6 +3710,7 @@ void MacroAssembler::reset_last_Java_frame(Register java_thread, bool clear_fp) // Always clear the pc because it could have been set by make_walkable() movptr(Address(java_thread, JavaThread::last_Java_pc_offset()), NULL_WORD); + vzeroupper(); } void MacroAssembler::restore_rax(Register tmp) { @@ -3714,6 +3753,7 @@ void MacroAssembler::set_last_Java_frame(Register java_thread, Register last_java_sp, Register last_java_fp, address last_java_pc) { + vzeroupper(); // determine java_thread register if (!java_thread->is_valid()) { java_thread = rdi; @@ -6552,10 +6592,8 @@ void MacroAssembler::restore_cpu_control_state_after_jni() { call(RuntimeAddress(StubRoutines::x86::verify_mxcsr_entry())); } } - if (VM_Version::supports_avx()) { - // Clear upper bits of YMM registers to avoid SSE <-> AVX transition penalty. - vzeroupper(); - } + // Clear upper bits of YMM registers to avoid SSE <-> AVX transition penalty. + vzeroupper(); #ifndef _LP64 // Either restore the x87 floating pointer control word after returning diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp index 2c2b17c06ad..f2bcbb12d30 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -71,12 +71,6 @@ class MacroAssembler: public Assembler { bool check_exceptions // whether to check for pending exceptions after return ); - // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. - // The implementation is only non-empty for the InterpreterMacroAssembler, - // as only the interpreter handles PopFrame and ForceEarlyReturn requests. - virtual void check_and_handle_popframe(Register java_thread); - virtual void check_and_handle_earlyret(Register java_thread); - void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true); // helpers for FPU flag access @@ -87,6 +81,12 @@ class MacroAssembler: public Assembler { public: MacroAssembler(CodeBuffer* code) : Assembler(code) {} + // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code. + // The implementation is only non-empty for the InterpreterMacroAssembler, + // as only the interpreter handles PopFrame and ForceEarlyReturn requests. + virtual void check_and_handle_popframe(Register java_thread); + virtual void check_and_handle_earlyret(Register java_thread); + // Support for NULL-checks // // Generates code that causes a NULL OS exception if the content of reg is NULL. @@ -456,6 +456,11 @@ class MacroAssembler: public Assembler { void fmad(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c); void fmaf(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c); + void vfmad(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c, int vector_len); + void vfmaf(XMMRegister dst, XMMRegister a, XMMRegister b, XMMRegister c, int vector_len); + void vfmad(XMMRegister dst, XMMRegister a, Address b, XMMRegister c, int vector_len); + void vfmaf(XMMRegister dst, XMMRegister a, Address b, XMMRegister c, int vector_len); + // same as fcmp2int, but using SSE2 void cmpss2int(XMMRegister opr1, XMMRegister opr2, Register dst, bool unordered_is_less); @@ -623,7 +628,7 @@ class MacroAssembler: public Assembler { void untested() { stop("untested"); } - void unimplemented(const char* what = "") { char* b = new char[1024]; jio_snprintf(b, 1024, "unimplemented: %s", what); stop(b); } + void unimplemented(const char* what = ""); void should_not_reach_here() { stop("should not reach here"); } diff --git a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_32.cpp b/hotspot/src/cpu/x86/vm/metaspaceShared_x86_32.cpp deleted file mode 100644 index c2956a52a54..00000000000 --- a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_32.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "asm/codeBuffer.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - Label common_code; - for (int i = 0; i < vtbl_list_size; ++i) { - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*)masm->pc(); - - // Load rax, with a value indicating vtable/offset pair. - // -- bits[ 7..0] (8 bits) which virtual method in table? - // -- bits[12..8] (5 bits) which virtual method table? - // -- must fit in 13-bit instruction immediate field. - __ movl(rax, (i << 8) + j); - __ jmp(common_code); - } - } - - __ bind(common_code); - -#ifdef WIN32 - // Expecting to be called with "thiscall" conventions -- the arguments - // are on the stack, except that the "this" pointer is in rcx. -#else - // Expecting to be called with Unix conventions -- the arguments - // are on the stack, including the "this" pointer. -#endif - - // In addition, rax was set (above) to the offset of the method in the - // table. - -#ifdef WIN32 - __ push(rcx); // save "this" -#endif - __ mov(rcx, rax); - __ shrptr(rcx, 8); // isolate vtable identifier. - __ shlptr(rcx, LogBytesPerWord); - Address index(noreg, rcx, Address::times_1); - ExternalAddress vtbl((address)vtbl_list); - __ movptr(rdx, ArrayAddress(vtbl, index)); // get correct vtable address. -#ifdef WIN32 - __ pop(rcx); // restore "this" -#else - __ movptr(rcx, Address(rsp, BytesPerWord)); // fetch "this" -#endif - __ movptr(Address(rcx, 0), rdx); // update vtable pointer. - - __ andptr(rax, 0x00ff); // isolate vtable method index - __ shlptr(rax, LogBytesPerWord); - __ addptr(rax, rdx); // address of real method pointer. - __ jmp(Address(rax, 0)); // get real method pointer. - - __ flush(); - - *mc_top = (char*)__ pc(); -} diff --git a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_64.cpp b/hotspot/src/cpu/x86/vm/metaspaceShared_x86_64.cpp deleted file mode 100644 index 4ff6cc955d7..00000000000 --- a/hotspot/src/cpu/x86/vm/metaspaceShared_x86_64.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "asm/codeBuffer.hpp" -#include "memory/metaspaceShared.hpp" - -// Generate the self-patching vtable method: -// -// This method will be called (as any other Klass virtual method) with -// the Klass itself as the first argument. Example: -// -// oop obj; -// int size = obj->klass()->oop_size(this); -// -// for which the virtual method call is Klass::oop_size(); -// -// The dummy method is called with the Klass object as the first -// operand, and an object as the second argument. -// - -//===================================================================== - -// All of the dummy methods in the vtable are essentially identical, -// differing only by an ordinal constant, and they bear no relationship -// to the original method which the caller intended. Also, there needs -// to be 'vtbl_list_size' instances of the vtable in order to -// differentiate between the 'vtable_list_size' original Klass objects. - -#define __ masm-> - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - - intptr_t vtable_bytes = (num_virtuals * vtbl_list_size) * sizeof(void*); - *(intptr_t *)(*md_top) = vtable_bytes; - *md_top += sizeof(intptr_t); - void** dummy_vtable = (void**)*md_top; - *vtable = dummy_vtable; - *md_top += vtable_bytes; - - // Get ready to generate dummy methods. - - CodeBuffer cb((unsigned char*)*mc_top, mc_end - *mc_top); - MacroAssembler* masm = new MacroAssembler(&cb); - - Label common_code; - for (int i = 0; i < vtbl_list_size; ++i) { - for (int j = 0; j < num_virtuals; ++j) { - dummy_vtable[num_virtuals * i + j] = (void*)masm->pc(); - - // Load eax with a value indicating vtable/offset pair. - // -- bits[ 7..0] (8 bits) which virtual method in table? - // -- bits[12..8] (5 bits) which virtual method table? - // -- must fit in 13-bit instruction immediate field. - __ movl(rax, (i << 8) + j); - __ jmp(common_code); - } - } - - __ bind(common_code); - - // Expecting to be called with "thiscall" convections -- the arguments - // are on the stack and the "this" pointer is in c_rarg0. In addition, rax - // was set (above) to the offset of the method in the table. - - __ push(c_rarg1); // save & free register - __ push(c_rarg0); // save "this" - __ mov(c_rarg0, rax); - __ shrptr(c_rarg0, 8); // isolate vtable identifier. - __ shlptr(c_rarg0, LogBytesPerWord); - __ lea(c_rarg1, ExternalAddress((address)vtbl_list)); // ptr to correct vtable list. - __ addptr(c_rarg1, c_rarg0); // ptr to list entry. - __ movptr(c_rarg1, Address(c_rarg1, 0)); // get correct vtable address. - __ pop(c_rarg0); // restore "this" - __ movptr(Address(c_rarg0, 0), c_rarg1); // update vtable pointer. - - __ andptr(rax, 0x00ff); // isolate vtable method index - __ shlptr(rax, LogBytesPerWord); - __ addptr(rax, c_rarg1); // address of real method pointer. - __ pop(c_rarg1); // restore register. - __ movptr(rax, Address(rax, 0)); // get real method pointer. - __ jmp(rax); // jump to the real method. - - __ flush(); - - *mc_top = (char*)__ pc(); -} diff --git a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp index 399172b5a15..dd582d9db44 100644 --- a/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp +++ b/hotspot/src/cpu/x86/vm/methodHandles_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -29,6 +29,7 @@ #include "interpreter/interpreterRuntime.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" +#include "prims/jvm.h" #include "prims/methodHandles.hpp" #define __ _masm-> @@ -65,7 +66,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm, Register obj, SystemDictionary::WKID klass_id, const char* error_message) { InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id); - KlassHandle klass = SystemDictionary::well_known_klass(klass_id); + Klass* klass = SystemDictionary::well_known_klass(klass_id); Register temp = rdi; Register temp2 = noreg; LP64_ONLY(temp2 = rscratch1); // used by MacroAssembler::cmpptr @@ -169,8 +170,9 @@ void MethodHandles::jump_to_lambda_form(MacroAssembler* _masm, __ verify_oop(method_temp); __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()))); __ verify_oop(method_temp); - // the following assumes that a Method* is normally compressed in the vmtarget field: - __ movptr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes()))); + __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()))); + __ verify_oop(method_temp); + __ movptr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes()))); if (VerifyMethodHandles && !for_compiler_entry) { // make sure recv is already on stack @@ -331,7 +333,8 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, Address member_clazz( member_reg, NONZERO(java_lang_invoke_MemberName::clazz_offset_in_bytes())); Address member_vmindex( member_reg, NONZERO(java_lang_invoke_MemberName::vmindex_offset_in_bytes())); - Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::vmtarget_offset_in_bytes())); + Address member_vmtarget( member_reg, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())); + Address vmtarget_method( rbx_method, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())); Register temp1_recv_klass = temp1; if (iid != vmIntrinsics::_linkToStatic) { @@ -383,14 +386,16 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm, if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp3); } - __ movptr(rbx_method, member_vmtarget); + __ load_heap_oop(rbx_method, member_vmtarget); + __ movptr(rbx_method, vmtarget_method); break; case vmIntrinsics::_linkToStatic: if (VerifyMethodHandles) { verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp3); } - __ movptr(rbx_method, member_vmtarget); + __ load_heap_oop(rbx_method, member_vmtarget); + __ movptr(rbx_method, vmtarget_method); break; case vmIntrinsics::_linkToVirtual: diff --git a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp index ef87c17807c..6fba4b8982b 100644 --- a/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp +++ b/hotspot/src/cpu/x86/vm/nativeInst_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, 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 @@ -715,8 +715,8 @@ inline bool NativeInstruction::is_safepoint_poll() { if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix && ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl && (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) || - ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl && - (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) { + (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl && + (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg)) { NOT_JVMCI(assert(Assembler::is_polling_page_far(), "unexpected poll encoding");) return true; } diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86.cpp index ed8cc4acacd..a68cbe811a2 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -39,7 +39,7 @@ // Since hashCode is usually polymorphic at call sites we can't do this // optimization at the call site without a lot of work. void SharedRuntime::inline_check_hashcode_from_object_header(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, Register obj_reg, Register result) { Label slowCase; diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index 47b9fe5c627..afd3525e70f 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -34,6 +34,7 @@ #include "oops/compiledICHolder.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/align.hpp" #include "vmreg_x86.inline.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" @@ -41,6 +42,7 @@ #ifdef COMPILER2 #include "opto/runtime.hpp" #endif +#include "vm_version_x86.hpp" #define __ masm-> @@ -120,8 +122,8 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ int zmm_bytes = num_xmm_regs * 32; #ifdef COMPILER2 if (save_vectors) { - assert(UseAVX > 0, "up to 512bit vectors are supported with EVEX"); - assert(MaxVectorSize <= 64, "up to 512bit vectors are supported now"); + assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX"); + assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); // Save upper half of YMM registers int vect_bytes = ymm_bytes; if (UseAVX > 2) { @@ -219,6 +221,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ } } } + __ vzeroupper(); // Set an oopmap for the call site. This oopmap will map all // oop-registers and debug-info registers as callee-saved. This @@ -269,8 +272,8 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve int additional_frame_bytes = 0; #ifdef COMPILER2 if (restore_vectors) { - assert(UseAVX > 0, "up to 512bit vectors are supported with EVEX"); - assert(MaxVectorSize <= 64, "up to 512bit vectors are supported now"); + assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX"); + assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); // Save upper half of YMM registers additional_frame_bytes = ymm_bytes; if (UseAVX > 2) { @@ -285,6 +288,8 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve int off = xmm0_off; int delta = xmm1_off - off; + __ vzeroupper(); + if (UseSSE == 1) { // Restore XMM registers assert(additional_frame_bytes == 0, ""); @@ -502,7 +507,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt, } // return value can be odd number of VMRegImpl stack slots make multiple of 2 - return round_to(stack, 2); + return align_up(stack, 2); } // Patch the callers callsite with entry to compiled code if it exists. @@ -778,9 +783,9 @@ void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm, // number (all values in registers) or the maximum stack slot accessed. // int comp_args_on_stack = VMRegImpl::reg2stack(max_arg); // Convert 4-byte stack slots to words. - comp_words_on_stack = round_to(comp_args_on_stack*4, wordSize)>>LogBytesPerWord; + comp_words_on_stack = align_up(comp_args_on_stack*4, wordSize)>>LogBytesPerWord; // Round up to miminum stack alignment, in wordSize - comp_words_on_stack = round_to(comp_words_on_stack, 2); + comp_words_on_stack = align_up(comp_words_on_stack, 2); __ subptr(rsp, comp_words_on_stack * wordSize); } @@ -1402,7 +1407,7 @@ static void unpack_array_argument(MacroAssembler* masm, VMRegPair reg, BasicType } static void verify_oop_args(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, const BasicType* sig_bt, const VMRegPair* regs) { Register temp_reg = rbx; // not part of any compiled calling seq @@ -1424,7 +1429,7 @@ static void verify_oop_args(MacroAssembler* masm, } static void gen_special_dispatch(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, const BasicType* sig_bt, const VMRegPair* regs) { verify_oop_args(masm, method, sig_bt, regs); @@ -1666,7 +1671,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, total_save_slots = double_slots * 2 + single_slots; // align the save area if (double_slots != 0) { - stack_slots = round_to(stack_slots, 2); + stack_slots = align_up(stack_slots, 2); } } @@ -1729,7 +1734,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Now compute actual number of stack words we need rounding to make // stack properly aligned. - stack_slots = round_to(stack_slots, StackAlignmentInSlots); + stack_slots = align_up(stack_slots, StackAlignmentInSlots); int stack_size = stack_slots * VMRegImpl::stack_slot_size; @@ -1994,7 +1999,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ movptr(swap_reg, 1); // Load (object->mark() | 1) into swap_reg %rax, - __ orptr(swap_reg, Address(obj_reg, 0)); + __ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); // Save (object->mark() | 1) into BasicLock's displaced header __ movptr(Address(lock_reg, mark_word_offset), swap_reg); @@ -2005,7 +2010,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // src -> dest iff dest == rax, else rax, <- dest // *obj_reg = lock_reg iff *obj_reg == rax, else rax, = *(obj_reg) - __ cmpxchgptr(lock_reg, Address(obj_reg, 0)); + __ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); __ jcc(Assembler::equal, lock_done); // Test if the oopMark is an obvious stack pointer, i.e., @@ -2123,6 +2128,8 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // preserved and correspond to the bcp/locals pointers. So we do a runtime call // by hand. // + __ vzeroupper(); + save_native_result(masm, ret_type, stack_slots); __ push(thread); if (!is_critical_native) { @@ -2198,7 +2205,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // src -> dest iff dest == rax, else rax, <- dest // *obj_reg = rbx, iff *obj_reg == rax, else rax, = *(obj_reg) - __ cmpxchgptr(rbx, Address(obj_reg, 0)); + __ cmpxchgptr(rbx, Address(obj_reg, oopDesc::mark_offset_in_bytes())); __ jcc(Assembler::notEqual, slow_path_unlock); // slow path re-enters here @@ -2304,7 +2311,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // BEGIN Slow path unlock __ bind(slow_path_unlock); - + __ vzeroupper(); // Slow path unlock if (ret_type == T_FLOAT || ret_type == T_DOUBLE ) { @@ -2349,6 +2356,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // SLOW PATH Reguard the stack if needed __ bind(reguard); + __ vzeroupper(); save_native_result(masm, ret_type, stack_slots); { __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages))); diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index d81e965d05d..12f5f76a451 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -37,6 +37,8 @@ #include "oops/compiledICHolder.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/vframeArray.hpp" +#include "utilities/align.hpp" +#include "vm_version_x86.hpp" #include "vmreg_x86.inline.hpp" #ifdef COMPILER1 #include "c1/c1_Runtime1.hpp" @@ -151,15 +153,15 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ } #if defined(COMPILER2) || INCLUDE_JVMCI if (save_vectors) { - assert(UseAVX > 0, "up to 512bit vectors are supported with EVEX"); - assert(MaxVectorSize <= 64, "up to 512bit vectors are supported now"); + assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX"); + assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); } #else assert(!save_vectors, "vectors are generated only by C2 and JVMCI"); #endif // Always make the frame size 16-byte aligned, both vector and non vector stacks are always allocated - int frame_size_in_bytes = round_to(reg_save_size*BytesPerInt, num_xmm_regs); + int frame_size_in_bytes = align_up(reg_save_size*BytesPerInt, num_xmm_regs); // OopMap frame size is in compiler stack slots (jint's) not bytes or words int frame_size_in_slots = frame_size_in_bytes / BytesPerInt; // CodeBlob frame size is in words. @@ -206,6 +208,7 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ } } } + __ vzeroupper(); if (frame::arg_reg_save_area_bytes != 0) { // Allocate argument register save area __ subptr(rsp, frame::arg_reg_save_area_bytes); @@ -322,13 +325,15 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve #if defined(COMPILER2) || INCLUDE_JVMCI if (restore_vectors) { - assert(UseAVX > 0, "up to 512bit vectors are supported with EVEX"); - assert(MaxVectorSize <= 64, "up to 512bit vectors are supported now"); + assert(UseAVX > 0, "Vectors larger than 16 byte long are supported only with AVX"); + assert(MaxVectorSize <= 64, "Only up to 64 byte long vectors are supported"); } #else assert(!restore_vectors, "vectors are generated only by C2"); #endif + __ vzeroupper(); + // On EVEX enabled targets everything is handled in pop fpu state if (restore_vectors) { // Restore upper half of YMM registers (0..15) @@ -509,7 +514,7 @@ int SharedRuntime::java_calling_convention(const BasicType *sig_bt, } } - return round_to(stk_args, 2); + return align_up(stk_args, 2); } // Patch the callers callsite with entry to compiled code if it exists. @@ -528,7 +533,7 @@ static void patch_callers_callsite(MacroAssembler *masm) { // align stack so push_CPU_state doesn't fault __ andptr(rsp, -(StackAlignmentInBytes)); __ push_CPU_state(); - + __ vzeroupper(); // VM needs caller's callsite // VM needs target method // This needs to be a long call since we will relocate this adapter to @@ -547,6 +552,7 @@ static void patch_callers_callsite(MacroAssembler *masm) { __ addptr(rsp, frame::arg_reg_save_area_bytes); } + __ vzeroupper(); __ pop_CPU_state(); // restore sp __ mov(rsp, r13); @@ -577,7 +583,7 @@ static void gen_c2i_adapter(MacroAssembler *masm, int extraspace = (total_args_passed * Interpreter::stackElementSize) + wordSize; // stack is aligned, keep it that way - extraspace = round_to(extraspace, 2*wordSize); + extraspace = align_up(extraspace, 2*wordSize); // Get return address __ pop(rax); @@ -777,9 +783,9 @@ void SharedRuntime::gen_i2c_adapter(MacroAssembler *masm, // number (all values in registers) or the maximum stack slot accessed. // Convert 4-byte c2 stack slots to words. - comp_words_on_stack = round_to(comp_args_on_stack*VMRegImpl::stack_slot_size, wordSize)>>LogBytesPerWord; + comp_words_on_stack = align_up(comp_args_on_stack*VMRegImpl::stack_slot_size, wordSize)>>LogBytesPerWord; // Round up to miminum stack alignment, in wordSize - comp_words_on_stack = round_to(comp_words_on_stack, 2); + comp_words_on_stack = align_up(comp_words_on_stack, 2); __ subptr(rsp, comp_words_on_stack * wordSize); } @@ -1465,7 +1471,6 @@ static void check_needs_gc_for_critical_native(MacroAssembler* masm, save_or_restore_arguments(masm, stack_slots, total_in_args, arg_save_area, NULL, in_regs, in_sig_bt); - __ bind(cont); #ifdef ASSERT if (StressCriticalJNINatives) { @@ -1735,7 +1740,7 @@ static void verify_oop_args(MacroAssembler* masm, } static void gen_special_dispatch(MacroAssembler* masm, - methodHandle method, + const methodHandle& method, const BasicType* sig_bt, const VMRegPair* regs) { verify_oop_args(masm, method, sig_bt, regs); @@ -1978,7 +1983,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, total_save_slots = double_slots * 2 + single_slots; // align the save area if (double_slots != 0) { - stack_slots = round_to(stack_slots, 2); + stack_slots = align_up(stack_slots, 2); } } @@ -2035,7 +2040,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Now compute actual number of stack words we need rounding to make // stack properly aligned. - stack_slots = round_to(stack_slots, StackAlignmentInSlots); + stack_slots = align_up(stack_slots, StackAlignmentInSlots); int stack_size = stack_slots * VMRegImpl::stack_slot_size; @@ -2368,7 +2373,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, __ movl(swap_reg, 1); // Load (object->mark() | 1) into swap_reg %rax - __ orptr(swap_reg, Address(obj_reg, 0)); + __ orptr(swap_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); // Save (object->mark() | 1) into BasicLock's displaced header __ movptr(Address(lock_reg, mark_word_offset), swap_reg); @@ -2378,7 +2383,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, } // src -> dest iff dest == rax else rax <- dest - __ cmpxchgptr(lock_reg, Address(obj_reg, 0)); + __ cmpxchgptr(lock_reg, Address(obj_reg, oopDesc::mark_offset_in_bytes())); __ jcc(Assembler::equal, lock_done); // Hmm should this move to the slow path code area??? @@ -2485,6 +2490,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // preserved and correspond to the bcp/locals pointers. So we do a runtime call // by hand. // + __ vzeroupper(); save_native_result(masm, ret_type, stack_slots); __ mov(c_rarg0, r15_thread); __ mov(r12, rsp); // remember sp @@ -2555,7 +2561,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, if (os::is_MP()) { __ lock(); } - __ cmpxchgptr(old_hdr, Address(obj_reg, 0)); + __ cmpxchgptr(old_hdr, Address(obj_reg, oopDesc::mark_offset_in_bytes())); __ jcc(Assembler::notEqual, slow_path_unlock); // slow path re-enters here @@ -2658,7 +2664,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // If we haven't already saved the native result we must save it now as xmm registers // are still exposed. - + __ vzeroupper(); if (ret_type == T_FLOAT || ret_type == T_DOUBLE ) { save_native_result(masm, ret_type, stack_slots); } @@ -2704,6 +2710,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // SLOW PATH Reguard the stack if needed __ bind(reguard); + __ vzeroupper(); save_native_result(masm, ret_type, stack_slots); __ mov(r12, rsp); // remember sp __ subptr(rsp, frame::arg_reg_save_area_bytes); // windows diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index d32917a5ab0..25eb6384c6b 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -1012,6 +1012,7 @@ class StubGenerator: public StubCodeGenerator { __ pop(rdi); __ pop(rsi); __ leave(); // required for proper stackwalking of RuntimeStub frame + __ vzeroupper(); __ xorptr(rax, rax); // return 0 __ ret(0); return start; @@ -1247,6 +1248,7 @@ class StubGenerator: public StubCodeGenerator { } inc_copy_counter_np(T_LONG); __ leave(); // required for proper stackwalking of RuntimeStub frame + __ vzeroupper(); __ xorptr(rax, rax); // return 0 __ ret(0); return start; @@ -3365,6 +3367,7 @@ class StubGenerator: public StubCodeGenerator { __ pop(rbx); __ pop(rdi); __ pop(rsi); + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -3422,6 +3425,7 @@ class StubGenerator: public StubCodeGenerator { __ pop(h); __ pop(g); __ pop(d); + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index 48be33ae526..bbe81875e91 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -402,6 +402,7 @@ class StubGenerator: public StubCodeGenerator { __ addptr(rsp, -rsp_after_call_off * wordSize); // return + __ vzeroupper(); __ pop(rbp); __ ret(0); @@ -1554,6 +1555,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -1643,6 +1645,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -1652,6 +1655,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jbyte_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -1746,6 +1750,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -1771,6 +1776,7 @@ class StubGenerator: public StubCodeGenerator { __ generate_fill(t, aligned, to, value, count, rax, xmm0); + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); return start; @@ -1847,6 +1853,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -1856,6 +1863,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jshort_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -1945,6 +1953,7 @@ class StubGenerator: public StubCodeGenerator { } restore_arg_regs(); inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free + __ vzeroupper(); __ xorptr(rax, rax); // return 0 __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -2030,6 +2039,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -2043,6 +2053,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jint_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -2120,6 +2131,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); } @@ -2137,6 +2149,7 @@ class StubGenerator: public StubCodeGenerator { } else { inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free } + __ vzeroupper(); __ xorptr(rax, rax); // return 0 __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -2203,6 +2216,7 @@ class StubGenerator: public StubCodeGenerator { restore_arg_regs(); inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free __ xorptr(rax, rax); // return 0 + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); } @@ -2220,6 +2234,7 @@ class StubGenerator: public StubCodeGenerator { } else { inc_counter_np(SharedRuntime::_jlong_array_copy_ctr); // Update counter after rscratch1 is free } + __ vzeroupper(); __ xorptr(rax, rax); // return 0 __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -3774,7 +3789,7 @@ class StubGenerator: public StubCodeGenerator { buf, state, ofs, limit, rsp, multi_block, shuf_mask); } __ addptr(rsp, 4 * wordSize); - + __ vzeroupper(); __ leave(); __ ret(0); return start; @@ -3808,6 +3823,7 @@ class StubGenerator: public StubCodeGenerator { __ sha512_AVX2(msg, state0, state1, msgtmp0, msgtmp1, msgtmp2, msgtmp3, msgtmp4, buf, state, ofs, limit, rsp, multi_block, shuf_mask); + __ vzeroupper(); __ leave(); __ ret(0); return start; @@ -4281,7 +4297,6 @@ class StubGenerator: public StubCodeGenerator { __ BIND(L_exit); __ pshufb(xmm_temp6, xmm_temp10); // Byte swap 16-byte result __ movdqu(Address(state, 0), xmm_temp6); // store the result - __ leave(); __ ret(0); return start; @@ -4321,6 +4336,7 @@ class StubGenerator: public StubCodeGenerator { __ kernel_crc32(crc, buf, len, table, tmp); __ movl(rax, crc); + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -4380,6 +4396,7 @@ class StubGenerator: public StubCodeGenerator { __ pop(z); __ pop(y); #endif + __ vzeroupper(); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); @@ -4494,6 +4511,7 @@ class StubGenerator: public StubCodeGenerator { __ vectorized_mismatch(obja, objb, length, scale, result, tmp1, tmp2, vec0, vec1, vec2); + __ vzeroupper(); __ leave(); __ ret(0); @@ -4618,7 +4636,7 @@ class StubGenerator: public StubCodeGenerator { BLOCK_COMMENT("Entry:"); __ enter(); // required for proper stackwalking of RuntimeStub frame - __ fast_exp(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp); + __ fast_exp(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp); __ leave(); // required for proper stackwalking of RuntimeStub frame __ ret(0); diff --git a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp index 9c02d44cdb8..e0a03daa358 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp @@ -171,16 +171,6 @@ address TemplateInterpreterGenerator::generate_exception_handler_common( return entry; } - -address TemplateInterpreterGenerator::generate_continuation_for(TosState state) { - address entry = __ pc(); - // NULL last_sp until next java call - __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), (int32_t)NULL_WORD); - __ dispatch_next(state); - return entry; -} - - address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, int step, size_t index_size) { address entry = __ pc(); @@ -230,6 +220,17 @@ address TemplateInterpreterGenerator::generate_return_entry_for(TosState state, __ movl(flags, Address(cache, index, Address::times_ptr, ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::flags_offset())); __ andl(flags, ConstantPoolCacheEntry::parameter_size_mask); __ lea(rsp, Address(rsp, flags, Interpreter::stackElementScale())); + + const Register java_thread = NOT_LP64(rcx) LP64_ONLY(r15_thread); + if (JvmtiExport::can_pop_frame()) { + NOT_LP64(__ get_thread(java_thread)); + __ check_and_handle_popframe(java_thread); + } + if (JvmtiExport::can_force_early_return()) { + NOT_LP64(__ get_thread(java_thread)); + __ check_and_handle_earlyret(java_thread); + } + __ dispatch_next(state, step); return entry; diff --git a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp index 3d2f57f37bc..60335333076 100644 --- a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp +++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp @@ -2622,6 +2622,7 @@ void TemplateTable::resolve_cache_and_index(int byte_no, switch (code) { case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break; case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break; + default: break; } assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range"); @@ -3287,6 +3288,7 @@ void TemplateTable::jvmti_post_fast_field_mod() { case Bytecodes::_fast_dputfield: __ pop(dtos); break; case Bytecodes::_fast_fputfield: __ pop(ftos); break; case Bytecodes::_fast_lputfield: __ pop_l(rax); break; + default: break; } __ bind(L2); } @@ -3846,7 +3848,7 @@ void TemplateTable::_new() { __ jcc(Assembler::notEqual, slow_case_no_pop); // get InstanceKlass - __ movptr(rcx, Address(rcx, rdx, Address::times_ptr, sizeof(ConstantPool))); + __ load_resolved_klass_at_index(rcx, rdx, rcx); __ push(rcx); // save the contexts of klass for initializing the header // make sure klass is initialized & doesn't have finalizer @@ -4061,8 +4063,7 @@ void TemplateTable::checkcast() { // Get superklass in rax and subklass in rbx __ bind(quicked); __ mov(rdx, rax); // Save object in rdx; rax needed for subtype check - __ movptr(rax, Address(rcx, rbx, - Address::times_ptr, sizeof(ConstantPool))); + __ load_resolved_klass_at_index(rcx, rbx, rax); __ bind(resolved); __ load_klass(rbx, rdx); @@ -4128,8 +4129,7 @@ void TemplateTable::instanceof() { // Get superklass in rax and subklass in rdx __ bind(quicked); __ load_klass(rdx, rax); - __ movptr(rax, Address(rcx, rbx, - Address::times_ptr, sizeof(ConstantPool))); + __ load_resolved_klass_at_index(rcx, rbx, rax); __ bind(resolved); diff --git a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp index 0307107ad9b..7fc5e451d08 100644 --- a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp @@ -74,6 +74,7 @@ declare_preprocessor_constant("VM_Version::CPU_AVX512BW", CPU_AVX512BW) \ declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) \ declare_preprocessor_constant("VM_Version::CPU_SHA", CPU_SHA) \ - declare_preprocessor_constant("VM_Version::CPU_FMA", CPU_FMA) + declare_preprocessor_constant("VM_Version::CPU_FMA", CPU_FMA) \ + declare_preprocessor_constant("VM_Version::CPU_VZEROUPPER", CPU_VZEROUPPER) #endif // CPU_X86_VM_VMSTRUCTS_X86_HPP diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index 197079ba1c7..99e402f8dee 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -26,7 +26,9 @@ #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" #include "logging/log.hpp" +#include "logging/logStream.hpp" #include "memory/resourceArea.hpp" +#include "prims/jvm.h" #include "runtime/java.hpp" #include "runtime/os.hpp" #include "runtime/stubCodeGenerator.hpp" @@ -436,14 +438,14 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ movl(rax, 0x10000); __ andl(rax, Address(rsi, 4)); __ cmpl(rax, 0x10000); - __ jccb(Assembler::notEqual, legacy_save_restore); + __ jcc(Assembler::notEqual, legacy_save_restore); // check _cpuid_info.xem_xcr0_eax.bits.opmask // check _cpuid_info.xem_xcr0_eax.bits.zmm512 // check _cpuid_info.xem_xcr0_eax.bits.zmm32 __ movl(rax, 0xE0); __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm __ cmpl(rax, 0xE0); - __ jccb(Assembler::notEqual, legacy_save_restore); + __ jcc(Assembler::notEqual, legacy_save_restore); // If UseAVX is unitialized or is set by the user to include EVEX if (use_evex) { @@ -469,11 +471,12 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ evmovdqul(xmm7, Address(rsp, 0), Assembler::AVX_512bit); __ addptr(rsp, 64); #endif // _WINDOWS + generate_vzeroupper(wrapup); VM_Version::clean_cpuFeatures(); UseAVX = saved_useavx; UseSSE = saved_usesse; __ jmp(wrapup); - } + } __ bind(legacy_save_restore); // AVX check @@ -498,6 +501,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ vmovdqu(xmm7, Address(rsp, 0)); __ addptr(rsp, 32); #endif // _WINDOWS + generate_vzeroupper(wrapup); VM_Version::clean_cpuFeatures(); UseAVX = saved_useavx; UseSSE = saved_usesse; @@ -513,6 +517,21 @@ class VM_Version_StubGenerator: public StubCodeGenerator { return start; }; + void generate_vzeroupper(Label& L_wrapup) { +# define __ _masm-> + __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset()))); + __ cmpl(Address(rsi, 4), 0x756e6547); // 'uneG' + __ jcc(Assembler::notEqual, L_wrapup); + __ movl(rcx, 0x0FFF0FF0); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset()))); + __ andl(rcx, Address(rsi, 0)); + __ cmpl(rcx, 0x00050670); // If it is Xeon Phi 3200/5200/7200 + __ jcc(Assembler::equal, L_wrapup); + __ cmpl(rcx, 0x00080650); // If it is Future Xeon Phi + __ jcc(Assembler::equal, L_wrapup); + __ vzeroupper(); +# undef __ + } }; void VM_Version::get_processor_features() { @@ -619,17 +638,22 @@ void VM_Version::get_processor_features() { if (UseAVX < 2) _features &= ~CPU_AVX2; - if (UseAVX < 1) + if (UseAVX < 1) { _features &= ~CPU_AVX; - - if (!UseAES && !FLAG_IS_DEFAULT(UseAES)) - _features &= ~CPU_AES; + _features &= ~CPU_VZEROUPPER; + } if (logical_processors_per_package() == 1) { // HT processor could be installed on a system which doesn't support HT. _features &= ~CPU_HT; } + if( is_intel() ) { // Intel cpus specific settings + if (is_knights_family()) { + _features &= ~CPU_VZEROUPPER; + } + } + char buf[256]; jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", cores_per_cpu(), threads_per_core(), @@ -785,7 +809,7 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseGHASHIntrinsics, false); } - if (supports_fma() && UseSSE >= 2) { + if (supports_fma() && UseSSE >= 2) { // Check UseSSE since FMA code uses SSE instructions if (FLAG_IS_DEFAULT(UseFMA)) { UseFMA = true; } @@ -861,7 +885,8 @@ void VM_Version::get_processor_features() { (_model == CPU_MODEL_BROADWELL && _stepping < 4)) { // currently a collision between SKL and HSW_E3 if (!UnlockExperimentalVMOptions && UseAVX < 3) { - vm_exit_during_initialization("UseRTMLocking is only available as experimental option on this platform. It must be enabled via -XX:+UnlockExperimentalVMOptions flag."); + vm_exit_during_initialization("UseRTMLocking is only available as experimental option on this " + "platform. It must be enabled via -XX:+UnlockExperimentalVMOptions flag."); } else { warning("UseRTMLocking is only available as experimental option on this platform."); } @@ -872,14 +897,6 @@ void VM_Version::get_processor_features() { // high lock contention. For now we do not use it by default. vm_exit_during_initialization("UseRTMLocking flag should be only set on command line"); } - if (!is_power_of_2(RTMTotalCountIncrRate)) { - warning("RTMTotalCountIncrRate must be a power of 2, resetting it to 64"); - FLAG_SET_DEFAULT(RTMTotalCountIncrRate, 64); - } - if (RTMAbortRatio < 0 || RTMAbortRatio > 100) { - warning("RTMAbortRatio must be in the range 0 to 100, resetting it to 50"); - FLAG_SET_DEFAULT(RTMAbortRatio, 50); - } } else { // !UseRTMLocking if (UseRTMForStackLocks) { if (!FLAG_IS_DEFAULT(UseRTMForStackLocks)) { @@ -917,16 +934,36 @@ void VM_Version::get_processor_features() { warning("MaxVectorSize must be a power of 2"); FLAG_SET_DEFAULT(MaxVectorSize, 64); } - if (MaxVectorSize > 64) { - FLAG_SET_DEFAULT(MaxVectorSize, 64); - } - if (MaxVectorSize > 16 && (UseAVX == 0 || !os_supports_avx_vectors())) { - // 32 bytes vectors (in YMM) are only supported with AVX+ - FLAG_SET_DEFAULT(MaxVectorSize, 16); - } if (UseSSE < 2) { // Vectors (in XMM) are only supported with SSE2+ - FLAG_SET_DEFAULT(MaxVectorSize, 0); + if (MaxVectorSize > 0) { + if (!FLAG_IS_DEFAULT(MaxVectorSize)) + warning("MaxVectorSize must be 0"); + FLAG_SET_DEFAULT(MaxVectorSize, 0); + } + } + else if (UseAVX == 0 || !os_supports_avx_vectors()) { + // 32 bytes vectors (in YMM) are only supported with AVX+ + if (MaxVectorSize > 16) { + if (!FLAG_IS_DEFAULT(MaxVectorSize)) + warning("MaxVectorSize must be <= 16"); + FLAG_SET_DEFAULT(MaxVectorSize, 16); + } + } + else if (UseAVX == 1 || UseAVX == 2) { + // 64 bytes vectors (in ZMM) are only supported with AVX 3 + if (MaxVectorSize > 32) { + if (!FLAG_IS_DEFAULT(MaxVectorSize)) + warning("MaxVectorSize must be <= 32"); + FLAG_SET_DEFAULT(MaxVectorSize, 32); + } + } + else if (UseAVX > 2 ) { + if (MaxVectorSize > 64) { + if (!FLAG_IS_DEFAULT(MaxVectorSize)) + warning("MaxVectorSize must be <= 64"); + FLAG_SET_DEFAULT(MaxVectorSize, 64); + } } #if defined(COMPILER2) && defined(ASSERT) if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) { @@ -1056,18 +1093,18 @@ void VM_Version::get_processor_features() { if ( cpu_family() == 0x15 ) { // On family 15h processors default is no sw prefetch if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) { - AllocatePrefetchStyle = 0; + FLAG_SET_DEFAULT(AllocatePrefetchStyle, 0); } // Also, if some other prefetch style is specified, default instruction type is PREFETCHW if (FLAG_IS_DEFAULT(AllocatePrefetchInstr)) { - AllocatePrefetchInstr = 3; + FLAG_SET_DEFAULT(AllocatePrefetchInstr, 3); } // On family 15h processors use XMM and UnalignedLoadStores for Array Copy if (supports_sse2() && FLAG_IS_DEFAULT(UseXMMForArrayCopy)) { - UseXMMForArrayCopy = true; + FLAG_SET_DEFAULT(UseXMMForArrayCopy, true); } if (supports_sse2() && FLAG_IS_DEFAULT(UseUnalignedLoadStores)) { - UseUnalignedLoadStores = true; + FLAG_SET_DEFAULT(UseUnalignedLoadStores, true); } } @@ -1132,10 +1169,7 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseSSE42Intrinsics, false); } } - if ((cpu_family() == 0x06) && - ((extended_cpu_model() == 0x36) || // Centerton - (extended_cpu_model() == 0x37) || // Silvermont - (extended_cpu_model() == 0x4D))) { + if (is_atom_family() || is_knights_family()) { #ifdef COMPILER2 if (FLAG_IS_DEFAULT(OptoScheduling)) { OptoScheduling = true; @@ -1146,9 +1180,12 @@ void VM_Version::get_processor_features() { UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus } } + if (FLAG_IS_DEFAULT(UseIncDec)) { + FLAG_SET_DEFAULT(UseIncDec, false); + } } if(FLAG_IS_DEFAULT(AllocatePrefetchInstr) && supports_3dnow_prefetch()) { - AllocatePrefetchInstr = 3; + FLAG_SET_DEFAULT(AllocatePrefetchInstr, 3); } } @@ -1244,45 +1281,68 @@ void VM_Version::get_processor_features() { } #endif // COMPILER2 - if( AllocatePrefetchInstr == 3 && !supports_3dnow_prefetch() ) AllocatePrefetchInstr=0; - if( !supports_sse() && supports_3dnow_prefetch() ) AllocatePrefetchInstr = 3; + if (FLAG_IS_DEFAULT(AllocatePrefetchInstr)) { + if (AllocatePrefetchInstr == 3 && !supports_3dnow_prefetch()) { + FLAG_SET_DEFAULT(AllocatePrefetchInstr, 0); + } else if (!supports_sse() && supports_3dnow_prefetch()) { + FLAG_SET_DEFAULT(AllocatePrefetchInstr, 3); + } + } // Allocation prefetch settings intx cache_line_size = prefetch_data_size(); - if( cache_line_size > AllocatePrefetchStepSize ) - AllocatePrefetchStepSize = cache_line_size; + if (FLAG_IS_DEFAULT(AllocatePrefetchStepSize) && + (cache_line_size > AllocatePrefetchStepSize)) { + FLAG_SET_DEFAULT(AllocatePrefetchStepSize, cache_line_size); + } - AllocatePrefetchDistance = allocate_prefetch_distance(); - AllocatePrefetchStyle = allocate_prefetch_style(); + if ((AllocatePrefetchDistance == 0) && (AllocatePrefetchStyle != 0)) { + assert(!FLAG_IS_DEFAULT(AllocatePrefetchDistance), "default value should not be 0"); + if (!FLAG_IS_DEFAULT(AllocatePrefetchStyle)) { + warning("AllocatePrefetchDistance is set to 0 which disable prefetching. Ignoring AllocatePrefetchStyle flag."); + } + FLAG_SET_DEFAULT(AllocatePrefetchStyle, 0); + } + + if (FLAG_IS_DEFAULT(AllocatePrefetchDistance)) { + bool use_watermark_prefetch = (AllocatePrefetchStyle == 2); + FLAG_SET_DEFAULT(AllocatePrefetchDistance, allocate_prefetch_distance(use_watermark_prefetch)); + } if (is_intel() && cpu_family() == 6 && supports_sse3()) { - if (AllocatePrefetchStyle == 2) { // watermark prefetching on Core -#ifdef _LP64 - AllocatePrefetchDistance = 384; -#else - AllocatePrefetchDistance = 320; -#endif - } - if (supports_sse4_2() && supports_ht()) { // Nehalem based cpus - AllocatePrefetchDistance = 192; - if (FLAG_IS_DEFAULT(AllocatePrefetchLines)) { - FLAG_SET_DEFAULT(AllocatePrefetchLines, 4); - } + if (FLAG_IS_DEFAULT(AllocatePrefetchLines) && + supports_sse4_2() && supports_ht()) { // Nehalem based cpus + FLAG_SET_DEFAULT(AllocatePrefetchLines, 4); } #ifdef COMPILER2 - if (supports_sse4_2()) { - if (FLAG_IS_DEFAULT(UseFPUForSpilling)) { - FLAG_SET_DEFAULT(UseFPUForSpilling, true); - } + if (FLAG_IS_DEFAULT(UseFPUForSpilling) && supports_sse4_2()) { + FLAG_SET_DEFAULT(UseFPUForSpilling, true); } #endif } #ifdef _LP64 // Prefetch settings - PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes(); - PrefetchScanIntervalInBytes = prefetch_scan_interval_in_bytes(); - PrefetchFieldsAhead = prefetch_fields_ahead(); + + // Prefetch interval for gc copy/scan == 9 dcache lines. Derived from + // 50-warehouse specjbb runs on a 2-way 1.8ghz opteron using a 4gb heap. + // Tested intervals from 128 to 2048 in increments of 64 == one cache line. + // 256 bytes (4 dcache lines) was the nearest runner-up to 576. + + // gc copy/scan is disabled if prefetchw isn't supported, because + // Prefetch::write emits an inlined prefetchw on Linux. + // Do not use the 3dnow prefetchw instruction. It isn't supported on em64t. + // The used prefetcht0 instruction works for both amd64 and em64t. + + if (FLAG_IS_DEFAULT(PrefetchCopyIntervalInBytes)) { + FLAG_SET_DEFAULT(PrefetchCopyIntervalInBytes, 576); + } + if (FLAG_IS_DEFAULT(PrefetchScanIntervalInBytes)) { + FLAG_SET_DEFAULT(PrefetchScanIntervalInBytes, 576); + } + if (FLAG_IS_DEFAULT(PrefetchFieldsAhead)) { + FLAG_SET_DEFAULT(PrefetchFieldsAhead, 1); + } #endif if (FLAG_IS_DEFAULT(ContendedPaddingWidth) && @@ -1296,7 +1356,8 @@ void VM_Version::get_processor_features() { #ifndef PRODUCT if (log_is_enabled(Info, os, cpu)) { - outputStream* log = Log(os, cpu)::info_stream(); + LogStream ls(Log(os, cpu)::info()); + outputStream* log = &ls; log->print_cr("Logical CPUs per core: %u", logical_processors_per_package()); log->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); @@ -1314,7 +1375,7 @@ void VM_Version::get_processor_features() { #endif log->cr(); log->print("Allocation"); - if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) { + if (AllocatePrefetchStyle <= 0 || (UseSSE == 0 && !supports_3dnow_prefetch())) { log->print_cr(": no prefetching"); } else { log->print(" prefetching: "); diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp index 5a51889e06b..23c2c7c195c 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp @@ -291,6 +291,7 @@ protected: #define CPU_AVX512VL ((uint64_t)UCONST64(0x200000000)) // EVEX instructions with smaller vector length #define CPU_SHA ((uint64_t)UCONST64(0x400000000)) // SHA instructions #define CPU_FMA ((uint64_t)UCONST64(0x800000000)) // FMA instructions +#define CPU_VZEROUPPER ((uint64_t)UCONST64(0x1000000000)) // Vzeroupper instruction enum Extended_Family { // AMD @@ -468,6 +469,7 @@ protected: _cpuid_info.xem_xcr0_eax.bits.sse != 0 && _cpuid_info.xem_xcr0_eax.bits.ymm != 0) { result |= CPU_AVX; + result |= CPU_VZEROUPPER; if (_cpuid_info.sef_cpuid7_ebx.bits.avx2 != 0) result |= CPU_AVX2; if (_cpuid_info.sef_cpuid7_ebx.bits.avx512f != 0 && @@ -605,8 +607,8 @@ public: static address cpuinfo_cont_addr() { return _cpuinfo_cont_addr; } static void clean_cpuFeatures() { _features = 0; } - static void set_avx_cpuFeatures() { _features = (CPU_SSE | CPU_SSE2 | CPU_AVX); } - static void set_evex_cpuFeatures() { _features = (CPU_AVX512F | CPU_SSE | CPU_SSE2 ); } + static void set_avx_cpuFeatures() { _features = (CPU_SSE | CPU_SSE2 | CPU_AVX | CPU_VZEROUPPER ); } + static void set_evex_cpuFeatures() { _features = (CPU_AVX512F | CPU_SSE | CPU_SSE2 | CPU_VZEROUPPER ); } // Initialization @@ -639,6 +641,8 @@ public: static bool is_P6() { return cpu_family() >= 6; } static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA' static bool is_intel() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x756e6547; } // 'uneG' + static bool is_atom_family() { return ((cpu_family() == 0x06) && ((extended_cpu_model() == 0x36) || (extended_cpu_model() == 0x37) || (extended_cpu_model() == 0x4D))); } //Silvermont and Centerton + static bool is_knights_family() { return ((cpu_family() == 0x06) && ((extended_cpu_model() == 0x57) || (extended_cpu_model() == 0x85))); } // Xeon Phi 3200/5200/7200 and Future Xeon Phi static bool supports_processor_topology() { return (_cpuid_info.std_max_function >= 0xB) && @@ -730,7 +734,9 @@ public: static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); } static bool supports_avxonly() { return ((supports_avx2() || supports_avx()) && !supports_evex()); } static bool supports_sha() { return (_features & CPU_SHA) != 0; } - static bool supports_fma() { return (_features & CPU_FMA) != 0; } + static bool supports_fma() { return (_features & CPU_FMA) != 0 && supports_avx(); } + static bool supports_vzeroupper() { return (_features & CPU_VZEROUPPER) != 0; } + // Intel features static bool is_intel_family_core() { return is_intel() && extended_cpu_family() == CPU_FAMILY_INTEL_CORE; } @@ -778,9 +784,7 @@ public: static bool supports_compare_and_exchange() { return true; } - static intx allocate_prefetch_distance() { - // This method should be called before allocate_prefetch_style(). - // + static intx allocate_prefetch_distance(bool use_watermark_prefetch) { // Hardware prefetching (distance/size in bytes): // Pentium 3 - 64 / 32 // Pentium 4 - 256 / 128 @@ -796,58 +800,34 @@ public: // Core - 256 / prefetchnta // It will be used only when AllocatePrefetchStyle > 0 - intx count = AllocatePrefetchDistance; - if (count < 0) { // default ? - if (is_amd()) { // AMD - if (supports_sse2()) - count = 256; // Opteron - else - count = 128; // Athlon - } else { // Intel - if (supports_sse2()) - if (cpu_family() == 6) { - count = 256; // Pentium M, Core, Core2 - } else { - count = 512; // Pentium 4 - } - else - count = 128; // Pentium 3 (and all other old CPUs) + if (is_amd()) { // AMD + if (supports_sse2()) { + return 256; // Opteron + } else { + return 128; // Athlon + } + } else { // Intel + if (supports_sse3() && cpu_family() == 6) { + if (supports_sse4_2() && supports_ht()) { // Nehalem based cpus + return 192; + } else if (use_watermark_prefetch) { // watermark prefetching on Core +#ifdef _LP64 + return 384; +#else + return 320; +#endif + } + } + if (supports_sse2()) { + if (cpu_family() == 6) { + return 256; // Pentium M, Core, Core2 + } else { + return 512; // Pentium 4 + } + } else { + return 128; // Pentium 3 (and all other old CPUs) } } - return count; - } - static intx allocate_prefetch_style() { - assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive"); - // Return 0 if AllocatePrefetchDistance was not defined. - return AllocatePrefetchDistance > 0 ? AllocatePrefetchStyle : 0; - } - - // Prefetch interval for gc copy/scan == 9 dcache lines. Derived from - // 50-warehouse specjbb runs on a 2-way 1.8ghz opteron using a 4gb heap. - // Tested intervals from 128 to 2048 in increments of 64 == one cache line. - // 256 bytes (4 dcache lines) was the nearest runner-up to 576. - - // gc copy/scan is disabled if prefetchw isn't supported, because - // Prefetch::write emits an inlined prefetchw on Linux. - // Do not use the 3dnow prefetchw instruction. It isn't supported on em64t. - // The used prefetcht0 instruction works for both amd64 and em64t. - static intx prefetch_copy_interval_in_bytes() { - intx interval = PrefetchCopyIntervalInBytes; - return interval >= 0 ? interval : 576; - } - static intx prefetch_scan_interval_in_bytes() { - intx interval = PrefetchScanIntervalInBytes; - return interval >= 0 ? interval : 576; - } - static intx prefetch_fields_ahead() { - intx count = PrefetchFieldsAhead; - return count >= 0 ? count : 1; - } - static uint32_t get_xsave_header_lower_segment() { - return _cpuid_info.xem_xcr0_eax.value; - } - static uint32_t get_xsave_header_upper_segment() { - return _cpuid_info.xem_xcr0_edx; } // SSE2 and later processors implement a 'pause' instruction diff --git a/hotspot/src/cpu/x86/vm/x86.ad b/hotspot/src/cpu/x86/vm/x86.ad index 3dd25561c0d..afaa2da23c7 100644 --- a/hotspot/src/cpu/x86/vm/x86.ad +++ b/hotspot/src/cpu/x86/vm/x86.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2011, 2017, 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 @@ -1387,7 +1387,7 @@ const int Matcher::min_vector_size(const BasicType bt) { } // Vector ideal reg corresponding to specidied size in bytes -const int Matcher::vector_ideal_reg(int size) { +const uint Matcher::vector_ideal_reg(int size) { assert(MaxVectorSize >= size, ""); switch(size) { case 4: return Op_VecS; @@ -1401,7 +1401,7 @@ const int Matcher::vector_ideal_reg(int size) { } // Only lowest bits of xmm reg are used for vector shift count. -const int Matcher::vector_shift_count_ideal_reg(int size) { +const uint Matcher::vector_shift_count_ideal_reg(int size) { return Op_VecS; } @@ -1804,9 +1804,9 @@ operand cmpOp_vcmppd() %{ instruct ShouldNotReachHere() %{ match(Halt); - format %{ "int3\t# ShouldNotReachHere" %} + format %{ "ud2\t# ShouldNotReachHere" %} ins_encode %{ - __ int3(); + __ ud2(); %} ins_pipe(pipe_slow); %} @@ -10520,3 +10520,161 @@ instruct vxor64B_mem(vecZ dst, vecZ src, memory mem) %{ ins_pipe( pipe_slow ); %} +// --------------------------------- FMA -------------------------------------- + +// a * b + c +instruct vfma2D_reg(vecX a, vecX b, vecX c) %{ + predicate(UseFMA && n->as_Vector()->length() == 2); + match(Set c (FmaVD c (Binary a b))); + format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed2D" %} + ins_cost(150); + ins_encode %{ + int vector_len = 0; + __ vfmad($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma2D_mem(vecX a, memory b, vecX c) %{ + predicate(UseFMA && n->as_Vector()->length() == 2); + match(Set c (FmaVD c (Binary a (LoadVector b)))); + format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed2D" %} + ins_cost(150); + ins_encode %{ + int vector_len = 0; + __ vfmad($c$$XMMRegister, $a$$XMMRegister, $b$$Address, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + + +// a * b + c +instruct vfma4D_reg(vecY a, vecY b, vecY c) %{ + predicate(UseFMA && n->as_Vector()->length() == 4); + match(Set c (FmaVD c (Binary a b))); + format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed4D" %} + ins_cost(150); + ins_encode %{ + int vector_len = 1; + __ vfmad($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma4D_mem(vecY a, memory b, vecY c) %{ + predicate(UseFMA && n->as_Vector()->length() == 4); + match(Set c (FmaVD c (Binary a (LoadVector b)))); + format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed4D" %} + ins_cost(150); + ins_encode %{ + int vector_len = 1; + __ vfmad($c$$XMMRegister, $a$$XMMRegister, $b$$Address, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma8D_reg(vecZ a, vecZ b, vecZ c) %{ + predicate(UseFMA && n->as_Vector()->length() == 8); + match(Set c (FmaVD c (Binary a b))); + format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed8D" %} + ins_cost(150); + ins_encode %{ + int vector_len = 2; + __ vfmad($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma8D_mem(vecZ a, memory b, vecZ c) %{ + predicate(UseFMA && n->as_Vector()->length() == 8); + match(Set c (FmaVD c (Binary a (LoadVector b)))); + format %{ "fmapd $a,$b,$c\t# $c = $a * $b + $c fma packed8D" %} + ins_cost(150); + ins_encode %{ + int vector_len = 2; + __ vfmad($c$$XMMRegister, $a$$XMMRegister, $b$$Address, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma4F_reg(vecX a, vecX b, vecX c) %{ + predicate(UseFMA && n->as_Vector()->length() == 4); + match(Set c (FmaVF c (Binary a b))); + format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed4F" %} + ins_cost(150); + ins_encode %{ + int vector_len = 0; + __ vfmaf($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma4F_mem(vecX a, memory b, vecX c) %{ + predicate(UseFMA && n->as_Vector()->length() == 4); + match(Set c (FmaVF c (Binary a (LoadVector b)))); + format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed4F" %} + ins_cost(150); + ins_encode %{ + int vector_len = 0; + __ vfmaf($c$$XMMRegister, $a$$XMMRegister, $b$$Address, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma8F_reg(vecY a, vecY b, vecY c) %{ + predicate(UseFMA && n->as_Vector()->length() == 8); + match(Set c (FmaVF c (Binary a b))); + format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed8F" %} + ins_cost(150); + ins_encode %{ + int vector_len = 1; + __ vfmaf($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma8F_mem(vecY a, memory b, vecY c) %{ + predicate(UseFMA && n->as_Vector()->length() == 8); + match(Set c (FmaVF c (Binary a (LoadVector b)))); + format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed8F" %} + ins_cost(150); + ins_encode %{ + int vector_len = 1; + __ vfmaf($c$$XMMRegister, $a$$XMMRegister, $b$$Address, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma16F_reg(vecZ a, vecZ b, vecZ c) %{ + predicate(UseFMA && n->as_Vector()->length() == 16); + match(Set c (FmaVF c (Binary a b))); + format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed16F" %} + ins_cost(150); + ins_encode %{ + int vector_len = 2; + __ vfmaf($c$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} + +// a * b + c +instruct vfma16F_mem(vecZ a, memory b, vecZ c) %{ + predicate(UseFMA && n->as_Vector()->length() == 16); + match(Set c (FmaVF c (Binary a (LoadVector b)))); + format %{ "fmaps $a,$b,$c\t# $c = $a * $b + $c fma packed16F" %} + ins_cost(150); + ins_encode %{ + int vector_len = 2; + __ vfmaf($c$$XMMRegister, $a$$XMMRegister, $b$$Address, $c$$XMMRegister, vector_len); + %} + ins_pipe( pipe_slow ); +%} diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index 3f045554ba2..cc711d2ec24 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -290,7 +290,7 @@ static int pre_call_resets_size() { if (C->in_24_bit_fp_mode()) { size += 6; // fldcw } - if (C->max_vector_size() > 16) { + if (VM_Version::supports_vzeroupper()) { size += 3; // vzeroupper } return size; @@ -329,7 +329,7 @@ bool SafePointNode::needs_polling_address_input() { int CallStaticJavaDirectNode::compute_padding(int current_offset) const { current_offset += pre_call_resets_size(); // skip fldcw, if any current_offset += 1; // skip call opcode byte - return round_to(current_offset, alignment_required()) - current_offset; + return align_up(current_offset, alignment_required()) - current_offset; } // The address of the call instruction needs to be 4-byte aligned to @@ -338,7 +338,7 @@ int CallDynamicJavaDirectNode::compute_padding(int current_offset) const { current_offset += pre_call_resets_size(); // skip fldcw, if any current_offset += 5; // skip MOV instruction current_offset += 1; // skip call opcode byte - return round_to(current_offset, alignment_required()) - current_offset; + return align_up(current_offset, alignment_required()) - current_offset; } // EMIT_RM() @@ -1884,7 +1884,6 @@ encode %{ } %} - enc_class pre_call_resets %{ // If method sets FPU control word restore it here debug_only(int off0 = cbuf.insts_size()); @@ -1892,12 +1891,10 @@ encode %{ MacroAssembler _masm(&cbuf); __ fldcw(ExternalAddress(StubRoutines::addr_fpu_cntrl_wrd_std())); } - if (ra_->C->max_vector_size() > 16) { - // Clear upper bits of YMM registers when current compiled code uses - // wide vectors to avoid AVX <-> SSE transition penalty during call. - MacroAssembler _masm(&cbuf); - __ vzeroupper(); - } + // Clear upper bits of YMM registers when current compiled code uses + // wide vectors to avoid AVX <-> SSE transition penalty during call. + MacroAssembler _masm(&cbuf); + __ vzeroupper(); debug_only(int off1 = cbuf.insts_size()); assert(off1 - off0 == pre_call_resets_size(), "correct size prediction"); %} @@ -3278,7 +3275,7 @@ frame %{ // Ret Addr is on stack in slot 0 if no locks or verification or alignment. // Otherwise, it is above the locks and verification slot and alignment word return_addr(STACK - 1 + - round_to((Compile::current()->in_preserve_stack_slots() + + align_up((Compile::current()->in_preserve_stack_slots() + Compile::current()->fixed_slots()), stack_alignment_in_slots())); @@ -13222,7 +13219,7 @@ instruct CallLeafNoFPDirect(method meth) %{ ins_cost(300); format %{ "CALL_LEAF_NOFP,runtime " %} opcode(0xE8); /* E8 cd */ - ins_encode(Java_To_Runtime(meth)); + ins_encode(pre_call_resets, Java_To_Runtime(meth)); ins_pipe( pipe_slow ); %} diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 41e3ab1fb9f..c96f28ddcd2 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -536,7 +536,7 @@ source %{ #define __ _masm. static int clear_avx_size() { - return (Compile::current()->max_vector_size() > 16) ? 3 : 0; // vzeroupper + return (VM_Version::supports_vzeroupper()) ? 3: 0; // vzeroupper } // !!!!! Special hack to get all types of calls to specify the byte offset @@ -579,7 +579,7 @@ int CallStaticJavaDirectNode::compute_padding(int current_offset) const { current_offset += clear_avx_size(); // skip vzeroupper current_offset += 1; // skip call opcode byte - return round_to(current_offset, alignment_required()) - current_offset; + return align_up(current_offset, alignment_required()) - current_offset; } // The address of the call instruction needs to be 4-byte aligned to @@ -588,7 +588,7 @@ int CallDynamicJavaDirectNode::compute_padding(int current_offset) const { current_offset += clear_avx_size(); // skip vzeroupper current_offset += 11; // skip movq instruction + call opcode byte - return round_to(current_offset, alignment_required()) - current_offset; + return align_up(current_offset, alignment_required()) - current_offset; } // EMIT_RM() @@ -919,7 +919,7 @@ int MachPrologNode::reloc() const void MachEpilogNode::format(PhaseRegAlloc* ra_, outputStream* st) const { Compile* C = ra_->C; - if (C->max_vector_size() > 16) { + if (VM_Version::supports_vzeroupper()) { st->print("vzeroupper"); st->cr(); st->print("\t"); } @@ -955,11 +955,9 @@ void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const Compile* C = ra_->C; MacroAssembler _masm(&cbuf); - if (C->max_vector_size() > 16) { - // Clear upper bits of YMM registers when current compiled code uses - // wide vectors to avoid AVX <-> SSE transition penalty during call. - __ vzeroupper(); - } + // Clear upper bits of YMM registers when current compiled code uses + // wide vectors to avoid AVX <-> SSE transition penalty during call. + __ vzeroupper(); int framesize = C->frame_size_in_bytes(); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); @@ -2092,12 +2090,11 @@ encode %{ enc_class clear_avx %{ debug_only(int off0 = cbuf.insts_size()); - if (ra_->C->max_vector_size() > 16) { - // Clear upper bits of YMM registers when current compiled code uses - // wide vectors to avoid AVX <-> SSE transition penalty during call. - MacroAssembler _masm(&cbuf); - __ vzeroupper(); - } + // Clear upper bits of YMM registers to avoid AVX <-> SSE transition penalty + // Clear upper bits of YMM registers when current compiled code uses + // wide vectors to avoid AVX <-> SSE transition penalty during call. + MacroAssembler _masm(&cbuf); + __ vzeroupper(); debug_only(int off1 = cbuf.insts_size()); assert(off1 - off0 == clear_avx_size(), "correct size prediction"); %} @@ -2810,7 +2807,7 @@ frame // Ret Addr is on stack in slot 0 if no locks or verification or alignment. // Otherwise, it is above the locks and verification slot and alignment word return_addr(STACK - 2 + - round_to((Compile::current()->in_preserve_stack_slots() + + align_up((Compile::current()->in_preserve_stack_slots() + Compile::current()->fixed_slots()), stack_alignment_in_slots())); @@ -12158,7 +12155,7 @@ instruct CallLeafNoFPDirect(method meth) ins_cost(300); format %{ "call_leaf_nofp,runtime " %} - ins_encode(Java_To_Runtime(meth)); + ins_encode(clear_avx, Java_To_Runtime(meth)); ins_pipe(pipe_slow); %} diff --git a/hotspot/src/cpu/zero/vm/abstractInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/abstractInterpreter_zero.cpp index de1a9584aeb..ee5f6aa888f 100644 --- a/hotspot/src/cpu/zero/vm/abstractInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/abstractInterpreter_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -29,10 +29,6 @@ #include "runtime/frame.inline.hpp" #include "utilities/globalDefinitions.hpp" -bool AbstractInterpreter::can_be_compiled(methodHandle m) { - return true; -} - int AbstractInterpreter::BasicType_as_index(BasicType type) { int i = 0; switch (type) { diff --git a/hotspot/src/cpu/zero/vm/bytes_zero.hpp b/hotspot/src/cpu/zero/vm/bytes_zero.hpp index 186f09d6937..9b56c01e586 100644 --- a/hotspot/src/cpu/zero/vm/bytes_zero.hpp +++ b/hotspot/src/cpu/zero/vm/bytes_zero.hpp @@ -36,16 +36,6 @@ typedef union unaligned { class Bytes: AllStatic { public: - // Returns true if the byte ordering used by Java is different - // from the native byte ordering of the underlying machine. - static inline bool is_Java_byte_ordering_different() { -#ifdef VM_LITTLE_ENDIAN - return true; -#else - return false; -#endif - } - // Efficient reading and writing of unaligned unsigned data in // platform-specific byte ordering. static inline u2 get_native_u2(address p){ diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index f7c51092c82..5c5a12a7085 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -378,14 +378,7 @@ int CppInterpreter::native_entry(Method* method, intptr_t UNUSED, TRAPS) { thread->set_thread_state(_thread_in_native_trans); // Make sure new state is visible in the GC thread - if (os::is_MP()) { - if (UseMembar) { - OrderAccess::fence(); - } - else { - InterfaceSupport::serialize_memory(thread); - } - } + InterfaceSupport::serialize_thread_state(thread); // Handle safepoint operations, pending suspend requests, // and pending asynchronous exceptions. diff --git a/hotspot/src/cpu/zero/vm/frame_zero.cpp b/hotspot/src/cpu/zero/vm/frame_zero.cpp index 19acf03681e..ad4887fb4d6 100644 --- a/hotspot/src/cpu/zero/vm/frame_zero.cpp +++ b/hotspot/src/cpu/zero/vm/frame_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -444,4 +444,6 @@ intptr_t *frame::initial_deoptimization_info() { frame::frame(void* sp, void* fp, void* pc) { Unimplemented(); } + +void frame::pd_ps() {} #endif diff --git a/hotspot/src/cpu/zero/vm/interpreterFrame_zero.hpp b/hotspot/src/cpu/zero/vm/interpreterFrame_zero.hpp index dd50aee8fd4..1cb658d18a3 100644 --- a/hotspot/src/cpu/zero/vm/interpreterFrame_zero.hpp +++ b/hotspot/src/cpu/zero/vm/interpreterFrame_zero.hpp @@ -30,6 +30,7 @@ #include "oops/method.hpp" #include "runtime/thread.hpp" #include "stack_zero.hpp" +#include "utilities/align.hpp" #ifdef CC_INTERP // | ... | @@ -57,8 +58,8 @@ class InterpreterFrame : public ZeroFrame { protected: enum Layout { istate_off = jf_header_words + - (align_size_up_(sizeof(BytecodeInterpreter), - wordSize) >> LogBytesPerWord) - 1, + (align_up_(sizeof(BytecodeInterpreter), + wordSize) >> LogBytesPerWord) - 1, header_words }; diff --git a/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp b/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp index 2e2dc3cab60..5078b40878c 100644 --- a/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp +++ b/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp @@ -35,6 +35,7 @@ #include "runtime/interfaceSupport.hpp" #include "runtime/signature.hpp" #include "stack_zero.inline.hpp" +#include "utilities/align.hpp" void InterpreterRuntime::SignatureHandlerGeneratorBase::pass_int() { push(T_INT); @@ -148,7 +149,7 @@ IRT_ENTRY(address, ZeroStack *stack = thread->zero_stack(); int required_words = - (align_size_up(sizeof(ffi_cif), wordSize) >> LogBytesPerWord) + + (align_up(sizeof(ffi_cif), wordSize) >> LogBytesPerWord) + (method->is_static() ? 2 : 1) + method->size_of_parameters() + 1; stack->overflow_check(required_words, CHECK_NULL); diff --git a/hotspot/src/cpu/zero/vm/interpreterRT_zero.hpp b/hotspot/src/cpu/zero/vm/interpreterRT_zero.hpp index 6330dd4fe4b..4d022bf2ec3 100644 --- a/hotspot/src/cpu/zero/vm/interpreterRT_zero.hpp +++ b/hotspot/src/cpu/zero/vm/interpreterRT_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -67,7 +67,7 @@ class SignatureHandlerGeneratorBase : public NativeSignatureIterator { ffi_cif* _cif; protected: - SignatureHandlerGeneratorBase(methodHandle method, ffi_cif *cif) + SignatureHandlerGeneratorBase(const methodHandle& method, ffi_cif *cif) : NativeSignatureIterator(method), _cif(cif) { _cif->nargs = 0; } @@ -96,7 +96,7 @@ class SignatureHandlerGenerator : public SignatureHandlerGeneratorBase { CodeBuffer* _cb; public: - SignatureHandlerGenerator(methodHandle method, CodeBuffer* buffer) + SignatureHandlerGenerator(const methodHandle& method, CodeBuffer* buffer) : SignatureHandlerGeneratorBase(method, (ffi_cif *) buffer->insts_end()), _cb(buffer) { _cb->set_insts_end((address) (cif() + 1)); @@ -115,7 +115,7 @@ class SlowSignatureHandlerGenerator : public SignatureHandlerGeneratorBase { intptr_t *_dst; public: - SlowSignatureHandlerGenerator(methodHandle method, intptr_t* buf) + SlowSignatureHandlerGenerator(const methodHandle& method, intptr_t* buf) : SignatureHandlerGeneratorBase(method, (ffi_cif *) buf) { _dst = (intptr_t *) (cif() + 1); } diff --git a/hotspot/src/cpu/zero/vm/metaspaceShared_zero.cpp b/hotspot/src/cpu/zero/vm/metaspaceShared_zero.cpp deleted file mode 100644 index 8cb5e15588f..00000000000 --- a/hotspot/src/cpu/zero/vm/metaspaceShared_zero.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. - * Copyright 2007 Red Hat, Inc. - * 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 "assembler_zero.inline.hpp" -#include "memory/metaspaceShared.hpp" - -void MetaspaceShared::generate_vtable_methods(void** vtbl_list, - void** vtable, - char** md_top, - char* md_end, - char** mc_top, - char* mc_end) { - ShouldNotCallThis(); -} diff --git a/hotspot/src/cpu/zero/vm/methodHandles_zero.cpp b/hotspot/src/cpu/zero/vm/methodHandles_zero.cpp index 8b7beb15547..b6ae15df6a2 100644 --- a/hotspot/src/cpu/zero/vm/methodHandles_zero.cpp +++ b/hotspot/src/cpu/zero/vm/methodHandles_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -147,8 +147,8 @@ int MethodHandles::method_handle_entry_linkToVirtual(Method* method, intptr_t UN Klass* clazz = recv->klass(); Klass* klass_part = InstanceKlass::cast(clazz); ResourceMark rm(THREAD); - klassVtable* vtable = klass_part->vtable(); - Method* vmtarget = vtable->method_at(vmindex); + klassVtable vtable = klass_part->vtable(); + Method* vmtarget = vtable.method_at(vmindex); invoke_target(vmtarget, THREAD); diff --git a/hotspot/src/cpu/zero/vm/stack_zero.cpp b/hotspot/src/cpu/zero/vm/stack_zero.cpp index 1acb96e97ec..a9bf5309921 100644 --- a/hotspot/src/cpu/zero/vm/stack_zero.cpp +++ b/hotspot/src/cpu/zero/vm/stack_zero.cpp @@ -28,6 +28,7 @@ #include "runtime/thread.hpp" #include "stack_zero.hpp" #include "stack_zero.inline.hpp" +#include "utilities/align.hpp" // Inlined causes circular inclusion with thread.hpp ZeroStack::ZeroStack() @@ -39,7 +40,7 @@ int ZeroStack::suggest_size(Thread *thread) const { assert(needs_setup(), "already set up"); int abi_available = abi_stack_available(thread); assert(abi_available >= 0, "available abi stack must be >= 0"); - return align_size_down(abi_available / 2, wordSize); + return align_down(abi_available / 2, wordSize); } void ZeroStack::handle_overflow(TRAPS) { diff --git a/hotspot/src/cpu/zero/vm/stack_zero.hpp b/hotspot/src/cpu/zero/vm/stack_zero.hpp index 6048cf2ac83..ca95c55a2b6 100644 --- a/hotspot/src/cpu/zero/vm/stack_zero.hpp +++ b/hotspot/src/cpu/zero/vm/stack_zero.hpp @@ -26,6 +26,7 @@ #ifndef CPU_ZERO_VM_STACK_ZERO_HPP #define CPU_ZERO_VM_STACK_ZERO_HPP +#include "utilities/align.hpp" #include "utilities/sizes.hpp" class ZeroStack { @@ -88,7 +89,7 @@ class ZeroStack { } void *alloc(size_t size) { - int count = align_size_up(size, wordSize) >> LogBytesPerWord; + int count = align_up(size, wordSize) >> LogBytesPerWord; assert(count <= available_words(), "stack overflow"); return _sp -= count; } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java index 6cd7a4ad8b0..f6201f6e341 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -36,16 +36,19 @@ import java.util.Map; import jdk.tools.jaotc.binformat.Symbol.Binding; import jdk.tools.jaotc.binformat.Symbol.Kind; import jdk.tools.jaotc.binformat.elf.JELFRelocObject; +import jdk.tools.jaotc.binformat.macho.JMachORelocObject; +import jdk.tools.jaotc.binformat.pecoff.JPECoffRelocObject; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.options.OptionValues; /** * A format-agnostic container class that holds various components of a binary. * *

    * This class holds information necessary to create platform-specific binary containers such as - * ELFContainer for Linux and Solaris operating systems or yet-to be created MachOContainer for Mac - * OS or PEContainer for MS Windows operating systems. + * ELFContainer for Linux and Solaris operating systems or MachOContainer for Mac OS or PEContainer + * for MS Windows operating systems. * *

    * Method APIs provided by this class are used to construct and populate platform-independent @@ -56,6 +59,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; * Methods to record and access code section contents, symbols and relocations are provided. */ public class BinaryContainer implements SymbolTable { + private final OptionValues graalOptions; private final int codeSegmentSize; @@ -257,36 +261,40 @@ public class BinaryContainer implements SymbolTable { * Allocates a {@code BinaryContainer} object whose content will be generated in a file with the * prefix {@code prefix}. It also initializes internal code container, symbol table and * relocation tables. + * + * @param graalOptions */ - public BinaryContainer(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, String jvmVersion) { + public BinaryContainer(OptionValues graalOptions, GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, String jvmVersion) { + this.graalOptions = graalOptions; + this.codeSegmentSize = graalHotSpotVMConfig.codeSegmentSize; this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment; // read only, code codeContainer = new CodeContainer(".text", this); - extLinkageContainer = new CodeContainer(".hotspot.linkage.plt", this); + extLinkageContainer = new CodeContainer(".hs.plt.linkage", this); // read only, info configContainer = new ReadOnlyDataContainer(".config", this); - metaspaceNamesContainer = new ReadOnlyDataContainer(".metaspace.names", this); + metaspaceNamesContainer = new ReadOnlyDataContainer(".meta.names", this); methodsOffsetsContainer = new ReadOnlyDataContainer(".methods.offsets", this); - klassesOffsetsContainer = new ReadOnlyDataContainer(".klasses.offsets", this); - klassesDependenciesContainer = new ReadOnlyDataContainer(".klasses.dependencies", this); + klassesOffsetsContainer = new ReadOnlyDataContainer(".kls.offsets", this); + klassesDependenciesContainer = new ReadOnlyDataContainer(".kls.dependencies", this); headerContainer = new HeaderContainer(jvmVersion, new ReadOnlyDataContainer(".header", this)); stubsOffsetsContainer = new ReadOnlyDataContainer(".stubs.offsets", this); codeSegmentsContainer = new ReadOnlyDataContainer(".code.segments", this); - constantDataContainer = new ReadOnlyDataContainer(".method.constdata", this); + constantDataContainer = new ReadOnlyDataContainer(".meth.constdata", this); // needs relocation patching at load time by the loader - methodMetadataContainer = new ReadOnlyDataContainer(".method.metadata", this); + methodMetadataContainer = new ReadOnlyDataContainer(".meth.metadata", this); // writable sections - metaspaceGotContainer = new ByteContainer(".metaspace.got", this); + metaspaceGotContainer = new ByteContainer(".meta.got", this); metadataGotContainer = new ByteContainer(".metadata.got", this); - methodStateContainer = new ByteContainer(".method.state", this); + methodStateContainer = new ByteContainer(".meth.state", this); oopGotContainer = new ByteContainer(".oop.got", this); - extLinkageGOTContainer = new ByteContainer(".hotspot.linkage.got", this); + extLinkageGOTContainer = new ByteContainer(".hs.got.linkage", this); addGlobalSymbols(); @@ -300,20 +308,19 @@ public class BinaryContainer implements SymbolTable { graalHotSpotVMConfig.useCompressedClassPointers, graalHotSpotVMConfig.compactFields, graalHotSpotVMConfig.useG1GC, - graalHotSpotVMConfig.useCMSGC, graalHotSpotVMConfig.useTLAB, graalHotSpotVMConfig.useBiasedLocking, - TieredAOT.getValue(), + TieredAOT.getValue(graalOptions), graalHotSpotVMConfig.enableContended, graalHotSpotVMConfig.restrictContended, graphBuilderConfig.omitAssertions() }; - int[] intFlags = { graalHotSpotVMConfig.getOopEncoding().shift, - graalHotSpotVMConfig.getKlassEncoding().shift, + int[] intFlags = { graalHotSpotVMConfig.getOopEncoding().getShift(), + graalHotSpotVMConfig.getKlassEncoding().getShift(), graalHotSpotVMConfig.contendedPaddingWidth, graalHotSpotVMConfig.fieldsAllocationStyle, - 1 << graalHotSpotVMConfig.getOopEncoding().alignment, + 1 << graalHotSpotVMConfig.logMinObjAlignment(), graalHotSpotVMConfig.codeSegmentSize, }; // @formatter:on @@ -497,11 +504,20 @@ public class BinaryContainer implements SymbolTable { switch (osName) { case "Linux": case "SunOS": - JELFRelocObject elfso = new JELFRelocObject(this, outputFileName, aotVersion); - elfso.createELFRelocObject(relocationTable, symbolTable.values()); + JELFRelocObject elfobj = new JELFRelocObject(this, outputFileName, aotVersion); + elfobj.createELFRelocObject(relocationTable, symbolTable.values()); + break; + case "Mac OS X": + JMachORelocObject machobj = new JMachORelocObject(this, outputFileName); + machobj.createMachORelocObject(relocationTable, symbolTable.values()); break; default: - throw new InternalError("Unsupported platform: " + osName); + if (osName.startsWith("Windows")) { + JPECoffRelocObject pecoffobj = new JPECoffRelocObject(this, outputFileName, aotVersion); + pecoffobj.createPECoffRelocObject(relocationTable, symbolTable.values()); + break; + } else + throw new InternalError("Unsupported platform: " + osName); } } @@ -742,11 +758,11 @@ public class BinaryContainer implements SymbolTable { } /** - * Add constant data as follows. - Adding the data to the method.constdata section + * Add constant data as follows. - Adding the data to the meth.constdata section * * @param data * @param alignment - * @return the offset in the method.constdata of the data + * @return the offset in the meth.constdata of the data */ public int addConstantData(byte[] data, int alignment) { // Get the current length of the metaspaceNameContainer diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java index 12daa9f356f..3d44ab0cf72 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/ByteContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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,7 +25,7 @@ package jdk.tools.jaotc.binformat; import jdk.tools.jaotc.binformat.Symbol.Binding; import jdk.tools.jaotc.binformat.Symbol.Kind; -import jdk.tools.jaotc.jnilibelf.ELFContainer; +import jdk.tools.jaotc.binformat.Container; import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; @@ -41,7 +41,7 @@ import java.util.Arrays; * The method {@code putIntAt} updates the content of {@code contentBytes}. Changes are not * reflected in {@code contentStream}. */ -public class ByteContainer implements ELFContainer { +public class ByteContainer implements Container { /** * {@code ByteBuffer} representation of {@code BinaryContainer}. */ diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java similarity index 87% rename from hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFContainer.java rename to hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java index b65b6ae8d25..ad2b405ab90 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFContainer.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Container.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -21,9 +21,9 @@ * questions. */ -package jdk.tools.jaotc.jnilibelf; +package jdk.tools.jaotc.binformat; -public interface ELFContainer { +public interface Container { String getContainerName(); diff --git a/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedCPU.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java similarity index 65% rename from hotspot/test/compiler/testlibrary/rtm/predicate/SupportedCPU.java rename to hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java index eab1f977723..e03870ebd40 100644 --- a/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedCPU.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/NativeSymbol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -21,17 +21,31 @@ * questions. */ -package compiler.testlibrary.rtm.predicate; +package jdk.tools.jaotc.binformat; -import jdk.test.lib.Platform; -import sun.hotspot.cpuinfo.CPUInfo; +/** + * This class represents ia native OS specific Symbol + */ +public abstract class NativeSymbol { -import java.util.function.BooleanSupplier; + /** String table index. */ + private int index; -public class SupportedCPU implements BooleanSupplier { - @Override - public boolean getAsBoolean() { - if (Platform.isPPC()) { return CPUInfo.hasFeature("tcheck"); } - return CPUInfo.hasFeature("rtm"); + public NativeSymbol(int index) { + this.index = index; + } + + /** + * @return the index + */ + public int getIndex() { + return index; + } + + /** + * @index + */ + public void setIndex(int index) { + this.index = index; } } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java index ba0f9090ee7..8fbc0dd23a6 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/Symbol.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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,7 +25,7 @@ package jdk.tools.jaotc.binformat; import java.util.Objects; -import jdk.tools.jaotc.jnilibelf.ELFSymbol; +import jdk.tools.jaotc.binformat.NativeSymbol; public class Symbol { @@ -51,7 +51,7 @@ public class Symbol { private final Kind kind; private ByteContainer section; - private ELFSymbol elfSymbol; + private NativeSymbol nativeSymbol; /** * Create symbol info. @@ -77,12 +77,12 @@ public class Symbol { return name; } - public ELFSymbol getElfSymbol() { - return elfSymbol; + public NativeSymbol getNativeSymbol() { + return nativeSymbol; } - public void setElfSymbol(ELFSymbol elfSymbol) { - this.elfSymbol = elfSymbol; + public void setNativeSymbol(NativeSymbol nativeSym) { + this.nativeSymbol = nativeSym; } public Binding getBinding() { diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java new file mode 100644 index 00000000000..e61176d07e7 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/Elf.java @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +/** + * + * Support for the creation of Elf Object files. + * Current support is limited to 64 bit x86_64. + * + */ + +public class Elf { + + /** + * Elf64_Ehdr structure defines + */ + public enum Elf64_Ehdr { + e_ident( 0,16), + e_type(16, 2), + e_machine(18, 2), + e_version(20, 4), + e_entry(24, 8), + e_phoff(32, 8), + e_shoff(40, 8), + e_flags(48, 4), + e_ehsize(52, 2), + e_phentsize(54, 2), + e_phnum(56, 2), + e_shentsize(58, 2), + e_shnum(60, 2), + e_shstrndx(62, 2); + + public final int off; + public final int sz; + + Elf64_Ehdr(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 64; + + /** + * Elf64_Ehdr defines + */ + + /** + * e_ident + */ + public static final int EI_MAG0 = 0; + public static final byte ELFMAG0 = 0x7f; + public static final int EI_MAG1 = 1; + public static final byte ELFMAG1 = 0x45; + public static final int EI_MAG2 = 2; + public static final byte ELFMAG2 = 0x4c; + public static final int EI_MAG3 = 3; + public static final byte ELFMAG3 = 0x46; + + public static final int EI_CLASS = 4; + public static final byte ELFCLASS64 = 0x2; + + public static final int EI_DATA = 5; + public static final byte ELFDATA2LSB = 0x1; + + public static final int EI_VERSION = 6; + public static final byte EV_CURRENT = 0x1; + + public static final int EI_OSABI = 7; + public static final byte ELFOSABI_NONE = 0x0; + + /** + * e_type + */ + public static final char ET_REL = 0x1; + + /** + * e_machine + */ + public static final char EM_NONE = 0; + public static final char EM_X86_64 = 62; + public static final char EM_AARCH64 = 183; + + /** + * e_version + */ + // public static final int EV_CURRENT = 1; + + } + + /** + * Elf64_Shdr structure defines + */ + public enum Elf64_Shdr { + sh_name( 0, 4), + sh_type( 4, 4), + sh_flags( 8, 8), + sh_addr(16, 8), + sh_offset(24, 8), + sh_size(32, 8), + sh_link(40, 4), + sh_info(44, 4), + sh_addralign(48, 8), + sh_entsize(56, 8); + + public final int off; + public final int sz; + + Elf64_Shdr(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 64; + + /** + * Elf64_Shdr defines + */ + + /** + * sh_type + */ + public static final int SHT_PROGBITS = 0x1; + public static final int SHT_SYMTAB = 0x2; + public static final int SHT_STRTAB = 0x3; + public static final int SHT_RELA = 0x4; + public static final int SHT_NOBITS = 0x8; + public static final int SHT_REL = 0x9; + + public static final byte SHN_UNDEF = 0x0; + + /** + * sh_flag + */ + public static final int SHF_WRITE = 0x1; + public static final int SHF_ALLOC = 0x2; + public static final int SHF_EXECINSTR = 0x4; + + } + + /** + * Symbol table entry definitions + * + * Elf64_Sym structure defines + */ + public enum Elf64_Sym { + st_name( 0, 4), + st_info( 4, 1), + st_other( 5, 1), + st_shndx( 6, 2), + st_value( 8, 8), + st_size(16, 8); + + public final int off; + public final int sz; + + Elf64_Sym(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 24; + + /* ST_BIND is in bits 4-7 of st_info. ST_TYPE is in low 4 bits */ + public static final byte STB_LOCAL = 0x0; + public static final byte STB_GLOBAL = 0x1; + + public static final byte STT_NOTYPE = 0x0; + public static final byte STT_OBJECT = 0x1; + public static final byte STT_FUNC = 0x2; + + public static byte ELF64_ST_INFO(byte bind, byte type) { + return (byte)(((bind) << 4) + ((type) & 0xf)); + } + + } + + /** + * Elf64_Rel structure defines + */ + public enum Elf64_Rel { + r_offset( 0, 8), + r_info( 8, 8); + + public final int off; + public final int sz; + + Elf64_Rel(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 16; + + /** + * Relocation types + */ + public static final int R_X86_64_NONE = 0x0; + public static final int R_X86_64_64 = 0x1; + public static final int R_X86_64_PC32 = 0x2; + public static final int R_X86_64_PLT32 = 0x4; + public static final int R_X86_64_GOTPCREL = 0x9; + + } + + /** + * Elf64_Rela structure defines + */ + public enum Elf64_Rela { + r_offset( 0, 8), + r_info( 8, 8), + r_addend(16, 8); + + public final int off; + public final int sz; + + Elf64_Rela(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 24; + + public static final int R_X86_64_NONE = 0x0; + public static final int R_X86_64_64 = 0x1; + public static final int R_X86_64_PC32 = 0x2; + public static final int R_X86_64_PLT32 = 0x4; + public static final int R_X86_64_GOTPCREL = 0x9; + + public static long ELF64_R_INFO(int symidx, int type) { + return (((long)symidx << 32) + ((long)type)); + } + + } + +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java new file mode 100644 index 00000000000..8d7c8e7d41d --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfByteBuffer.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; + +public class ElfByteBuffer { + + public static ByteBuffer allocate(int size) { + ByteBuffer buf = ByteBuffer.allocate(size); + if (ElfTargetInfo.getElfEndian() == Elf64_Ehdr.ELFDATA2LSB) + buf.order(ByteOrder.LITTLE_ENDIAN); + else + buf.order(ByteOrder.BIG_ENDIAN); + return (buf); + } + +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java new file mode 100644 index 00000000000..03b8682c95e --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfContainer.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.io.File; +import java.io.FileOutputStream; + +public class ElfContainer { + + File outputFile; + FileOutputStream outputStream; + long fileOffset; + + public ElfContainer(String fileName, String aotVersion) { + String baseName; + + outputFile = new File(fileName); + if (outputFile.exists()) { + outputFile.delete(); + } + + try { + outputStream = new FileOutputStream(outputFile); + } catch (Exception e) { + System.out.println("ElfContainer: Can't create file " + fileName); + } + fileOffset = 0; + } + + public void close() { + try { + outputStream.close(); + } catch (Exception e) { + System.out.println("ElfContainer: close failed"); + } + } + + public void writeBytes(byte [] bytes) { + if (bytes == null) return; + try { + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("ElfContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } + + // Write bytes to output file with up front alignment padding + public void writeBytes(byte [] bytes, int alignment) { + if (bytes == null) return; + try { + // Pad to alignment + while ((fileOffset & (long)(alignment-1)) != 0) { + outputStream.write(0); + fileOffset++; + } + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("ElfContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java new file mode 100644 index 00000000000..e930d5580a3 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfHeader.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfHeader { + ByteBuffer header; + + public ElfHeader() { + header = ElfByteBuffer.allocate(Elf64_Ehdr.totalsize); + + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG0, Elf64_Ehdr.ELFMAG0); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG1, Elf64_Ehdr.ELFMAG1); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG2, Elf64_Ehdr.ELFMAG2); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_MAG3, Elf64_Ehdr.ELFMAG3); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_CLASS, Elf64_Ehdr.ELFCLASS64); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_DATA, Elf64_Ehdr.ELFDATA2LSB); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_VERSION, Elf64_Ehdr.EV_CURRENT); + header.put(Elf64_Ehdr.e_ident.off+Elf64_Ehdr.EI_OSABI, Elf64_Ehdr.ELFOSABI_NONE); + + header.putChar(Elf64_Ehdr.e_type.off, Elf64_Ehdr.ET_REL); + header.putChar(Elf64_Ehdr.e_machine.off, ElfTargetInfo.getElfArch()); + header.putInt(Elf64_Ehdr.e_version.off, Elf64_Ehdr.EV_CURRENT); + header.putChar(Elf64_Ehdr.e_ehsize.off, (char)Elf64_Ehdr.totalsize); + header.putChar(Elf64_Ehdr.e_shentsize.off, (char)Elf64_Shdr.totalsize); + + } + + // Update header with file offset of first section + public void setSectionOff(int offset) { + header.putLong(Elf64_Ehdr.e_shoff.off, offset); + } + + // Update header with the number of total sections + public void setSectionNum(int count) { + header.putChar(Elf64_Ehdr.e_shnum.off, (char)count); + } + + // Update header with the section index containing the + // string table for section names + public void setSectionStrNdx(int index) { + header.putChar(Elf64_Ehdr.e_shstrndx.off, (char)index); + } + + public byte[] getArray() { + return header.array(); + } +} + diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/writer/DumpWriter.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java similarity index 55% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/writer/DumpWriter.java rename to hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java index 47a7ca3905e..817648ec65b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/writer/DumpWriter.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -20,32 +20,32 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.salver.writer; -import java.io.Closeable; -import java.io.Flushable; -import java.io.IOException; +package jdk.tools.jaotc.binformat.elf; + import java.nio.ByteBuffer; +import java.nio.ByteOrder; -public interface DumpWriter extends Closeable, Flushable, AutoCloseable { +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; - DumpWriter write(byte b) throws IOException; +public class ElfRelocEntry { + ByteBuffer entry; - DumpWriter write(byte[] arr) throws IOException; + public ElfRelocEntry(int offset, int symno, int type, int addend) { - DumpWriter write(ByteBuffer buf) throws IOException; + entry = ElfByteBuffer.allocate(Elf64_Rela.totalsize); - DumpWriter write(CharSequence csq) throws IOException; + entry.putLong(Elf64_Rela.r_offset.off, offset); + entry.putLong(Elf64_Rela.r_info.off, Elf64_Rela.ELF64_R_INFO(symno,type)); + entry.putLong(Elf64_Rela.r_addend.off, addend); + } - DumpWriter writeChar(char v) throws IOException; - - DumpWriter writeShort(short v) throws IOException; - - DumpWriter writeInt(int v) throws IOException; - - DumpWriter writeLong(long v) throws IOException; - - DumpWriter writeFloat(float v) throws IOException; - - DumpWriter writeDouble(double v) throws IOException; + public byte[] getArray() { + return entry.array(); + } } + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java new file mode 100644 index 00000000000..0e28a9f384e --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfRelocTable.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.util.ArrayList; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.elf.ElfRelocEntry; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfRelocTable { + ArrayList> relocEntries; + + public ElfRelocTable(int numsects) { + relocEntries = new ArrayList>(numsects); + for (int i = 0; i < numsects; i++) + relocEntries.add(new ArrayList()); + } + + public void createRelocationEntry(int sectindex, + int offset, + int symno, + int type, + int addend) { + + ElfRelocEntry entry = new ElfRelocEntry(offset, + symno, + type, + addend); + relocEntries.get(sectindex).add(entry); + } + + public int getNumRelocs(int section_index) { + return relocEntries.get(section_index).size(); + } + + // Return the relocation entries for a single section + // or null if no entries added to section + public byte [] getRelocData(int section_index) { + ArrayList entryList = relocEntries.get(section_index); + + if (entryList.size() == 0) + return null; + + ByteBuffer relocData = ElfByteBuffer.allocate(entryList.size() * Elf64_Rela.totalsize); + + // Copy each entry to a single ByteBuffer + for (int i = 0; i < entryList.size(); i++) { + ElfRelocEntry entry = entryList.get(i); + relocData.put(entry.getArray()); + } + + return (relocData.array()); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java new file mode 100644 index 00000000000..86415d23cca --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSection.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rel; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfSection { + String name; + ByteBuffer section; + byte [] data; + boolean hasrelocations; + int sectionIndex; + + /** + * String holding section name strings + */ + private static StringBuilder sectNameTab = new StringBuilder(); + + /** + * Keeps track of bytes in section string table since strTabContent.length() + * is number of chars, not bytes. + */ + private static int shStrTabNrOfBytes = 0; + + public ElfSection(String sectName, byte [] sectData, int sectFlags, + int sectType, boolean hasRelocations, int align, + int sectIndex) { + + section = ElfByteBuffer.allocate(Elf64_Shdr.totalsize); + + // Return all 0's for NULL section + if (sectIndex == 0) { + sectNameTab.append('\0'); + shStrTabNrOfBytes += 1; + data = null; + hasrelocations = false; + sectionIndex = 0; + return; + } + + section.putInt(Elf64_Shdr.sh_name.off, shStrTabNrOfBytes); + sectNameTab.append(sectName).append('\0'); + shStrTabNrOfBytes += (sectName.getBytes().length + 1); + name = sectName; + + section.putInt(Elf64_Shdr.sh_type.off, sectType); + section.putLong(Elf64_Shdr.sh_flags.off, sectFlags); + section.putLong(Elf64_Shdr.sh_addr.off, 0); + section.putLong(Elf64_Shdr.sh_offset.off, 0); + + if (sectName.equals(".shstrtab")) { + section.putLong(Elf64_Shdr.sh_size.off, shStrTabNrOfBytes); + data = sectNameTab.toString().getBytes(); + } + else { + data = sectData; + section.putLong(Elf64_Shdr.sh_size.off, sectData.length); + } + + section.putLong(Elf64_Shdr.sh_entsize.off, 0); + + // Determine the entrysize + // based on type of section + switch (sectType) { + case Elf64_Shdr.SHT_SYMTAB: + section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Sym.totalsize); + break; + case Elf64_Shdr.SHT_RELA: + section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Rela.totalsize); + break; + case Elf64_Shdr.SHT_REL: + section.putLong(Elf64_Shdr.sh_entsize.off, Elf64_Rel.totalsize); + break; + default: + break; + } + section.putLong(Elf64_Shdr.sh_addralign.off, align); + + hasrelocations = hasRelocations; + sectionIndex = sectIndex; + } + + public String getName() { + return name; + } + + public long getSize() { + return section.getLong(Elf64_Shdr.sh_size.off); + } + + public int getDataAlign() { + return ((int)section.getLong(Elf64_Shdr.sh_addralign.off)); + } + + // Alignment requirements for the Elf64_Shdr structures + public static int getShdrAlign() { + return (4); + } + + public byte[] getArray() { + return section.array(); + } + + public byte[] getDataArray() { + return data; + } + + public void setOffset(long offset) { + section.putLong(Elf64_Shdr.sh_offset.off, offset); + } + + public void setLink(int link) { + section.putInt(Elf64_Shdr.sh_link.off, link); + } + + public void setInfo(int info) { + section.putInt(Elf64_Shdr.sh_info.off, info); + } + + public long getOffset() { + return (section.getLong(Elf64_Shdr.sh_offset.off)); + } + + public boolean hasRelocations() { + return hasrelocations; + } + + public int getSectionId() { + return sectionIndex; + } + +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java new file mode 100644 index 00000000000..6a22019f6bf --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymbol.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfSymbol extends NativeSymbol { + ByteBuffer sym; + + public ElfSymbol(int symbolindex, int strindex, byte type, byte bind, + byte sectindex, long offset, long size) { + super(symbolindex); + sym = ElfByteBuffer.allocate(Elf64_Sym.totalsize); + + sym.putInt(Elf64_Sym.st_name.off, strindex); + sym.put(Elf64_Sym.st_info.off, Elf64_Sym.ELF64_ST_INFO(bind, type)); + sym.put(Elf64_Sym.st_other.off, (byte)0); + // Section indexes start at 1 but we manage the index internally + // as 0 relative + sym.putChar(Elf64_Sym.st_shndx.off, (char)(sectindex)); + sym.putLong(Elf64_Sym.st_value.off, offset); + sym.putLong(Elf64_Sym.st_size.off, size); + } + + public byte[] getArray() { + return sym.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java new file mode 100644 index 00000000000..4105c152693 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfSymtab.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; + +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.tools.jaotc.binformat.elf.ElfSymbol; +import jdk.tools.jaotc.binformat.elf.ElfByteBuffer; + +public class ElfSymtab { + + ArrayListlocalSymbols = new ArrayList(); + ArrayListglobalSymbols = new ArrayList(); + + /** + * number of symbols added + */ + int symbolCount; + + /** + * String holding symbol table strings + */ + private StringBuilder strTabContent = new StringBuilder(); + + /** + * Keeps track of bytes in string table since strTabContent.length() + * is number of chars, not bytes. + */ + private int strTabNrOfBytes = 0; + + public ElfSymtab() { + symbolCount = 0; + } + + public ElfSymbol addSymbolEntry(String name, byte type, byte bind, + byte secHdrIndex, long offset, long size) { + // Get the current symbol index and append symbol name to string table. + int index; + ElfSymbol sym; + + if (name.isEmpty()) { + index = 0; + strTabContent.append('\0'); + strTabNrOfBytes += 1; + sym = new ElfSymbol(symbolCount, index, type, bind, secHdrIndex, offset, size); + localSymbols.add(sym); + } else { + // We can't trust strTabContent.length() since that is + // chars (UTF16), keep track of bytes on our own. + index = strTabNrOfBytes; + // strTabContent.append("_").append(name).append('\0'); + strTabContent.append(name).append('\0'); + // + 1 for null, + 1 for "_" + //strTabNrOfBytes += (name.getBytes().length + 1 + 1); + strTabNrOfBytes += (name.getBytes().length + 1); + + sym = new ElfSymbol(symbolCount, index, type, bind, secHdrIndex, offset, size); + if ((bind & Elf64_Sym.STB_GLOBAL) != 0) + globalSymbols.add(sym); + else + localSymbols.add(sym); + } + symbolCount++; + return (sym); + } + + // Update the symbol indexes once all symbols have been added. + // This is required since we'll be reordering the symbols in the + // file to be in the order of Local then global. + public void updateIndexes() { + int index = 0; + + // Update the local symbol indexes + for (int i = 0; i < localSymbols.size(); i++ ) { + ElfSymbol sym = localSymbols.get(i); + sym.setIndex(index++); + } + + // Update the global symbol indexes + for (int i = 0; i < globalSymbols.size(); i++ ) { + ElfSymbol sym = globalSymbols.get(i); + sym.setIndex(index++); + } + } + + public int getNumLocalSyms() { return localSymbols.size(); } + public int getNumGlobalSyms() { return globalSymbols.size(); } + + + // Create a single byte array that contains the symbol table entries + public byte[] getSymtabArray() { + int index = 0; + ByteBuffer symtabData = ElfByteBuffer.allocate(symbolCount*Elf64_Sym.totalsize); + byte [] retarray; + + updateIndexes(); + + // Add the local symbols + for (int i = 0; i < localSymbols.size(); i++ ) { + ElfSymbol sym = localSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + // Add the global symbols + for (int i = 0; i < globalSymbols.size(); i++ ) { + ElfSymbol sym = globalSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + retarray = symtabData.array(); + + return (retarray); + } + + // Return the string table array + public byte[] getStrtabArray() { + byte [] strs = strTabContent.toString().getBytes(); + return (strs); + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java new file mode 100644 index 00000000000..2c9a6a3c4a0 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/ElfTargetInfo.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.elf; + +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; + +/** + * Class that abstracts MACH-O target details. + * + */ +public class ElfTargetInfo { + /** + * Target architecture. + */ + private static final char arch; + + /** + * Architecture endian-ness. + */ + private static final int endian = Elf64_Ehdr.ELFDATA2LSB; + + /** + * Target OS string. + */ + private static String osName; + + static { + // Find the target arch details + String archStr = System.getProperty("os.arch").toLowerCase(); + if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) { + System.out.println("Only Little Endian byte order supported!"); + } + + if (archStr.equals("amd64") || archStr.equals("x86_64")) { + arch = Elf64_Ehdr.EM_X86_64; + } else { + System.out.println("Unsupported architecture " + archStr); + arch = Elf64_Ehdr.EM_NONE; + } + + osName = System.getProperty("os.name").toLowerCase(); + if (!osName.equals("linux") && !osName.equals("sunos")) { + System.out.println("Unsupported Operating System " + osName); + osName = "Unknown"; + } + } + + public static char getElfArch() { + return arch; + } + + public static int getElfEndian() { + return endian; + } + + public static String getOsName() { + return osName; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java index 82bac0c7170..b288b554708 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/elf/JELFRelocObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -30,6 +30,7 @@ import java.util.Collection; import java.util.List; import java.util.Map; +import jdk.tools.jaotc.binformat.Container; import jdk.tools.jaotc.binformat.BinaryContainer; import jdk.tools.jaotc.binformat.ByteContainer; import jdk.tools.jaotc.binformat.CodeContainer; @@ -37,36 +38,62 @@ import jdk.tools.jaotc.binformat.ReadOnlyDataContainer; import jdk.tools.jaotc.binformat.Relocation; import jdk.tools.jaotc.binformat.Relocation.RelocType; import jdk.tools.jaotc.binformat.Symbol; +import jdk.tools.jaotc.binformat.NativeSymbol; import jdk.tools.jaotc.binformat.Symbol.Binding; import jdk.tools.jaotc.binformat.Symbol.Kind; -import jdk.tools.jaotc.jnilibelf.ELFContainer; -import jdk.tools.jaotc.jnilibelf.ELFSymbol; -import jdk.tools.jaotc.jnilibelf.JNIELFContainer; -import jdk.tools.jaotc.jnilibelf.JNIELFRelocation; -import jdk.tools.jaotc.jnilibelf.JNIELFTargetInfo; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Cmd; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Type; -import jdk.tools.jaotc.jnilibelf.Pointer; + +import jdk.tools.jaotc.binformat.elf.Elf; +import jdk.tools.jaotc.binformat.elf.ElfSymbol; +import jdk.tools.jaotc.binformat.elf.ElfTargetInfo; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Ehdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Shdr; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rel; +import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Rela; public class JELFRelocObject { private final BinaryContainer binContainer; - private final JNIELFContainer elfContainer; + private final ElfContainer elfContainer; private final int segmentSize; public JELFRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) { this.binContainer = binContainer; - this.elfContainer = new JNIELFContainer(outputFileName, aotVersion); + this.elfContainer = new ElfContainer(outputFileName, aotVersion); this.segmentSize = binContainer.getCodeSegmentSize(); } - private void createByteSection(ByteContainer c, int scnFlags) { + private ElfSection createByteSection(ArrayListsections, + String sectName, + byte [] scnData, + boolean hasRelocs, + int align, + int scnFlags, + int scnType) { + + ElfSection sect = new ElfSection(sectName, + scnData, + scnFlags, + scnType, + hasRelocs, + align, + sections.size()); + // Add this section to our list + sections.add(sect); + + return (sect); + } + + private void createByteSection(ArrayListsections, + ByteContainer c, int scnFlags) { + ElfSection sect; + boolean hasRelocs = c.hasRelocations(); byte[] scnData = c.getByteArray(); - int scnType = ELF.SHT_PROGBITS; - boolean zeros = !c.hasRelocations(); + + int scnType = Elf64_Shdr.SHT_PROGBITS; + boolean zeros = !hasRelocs; if (zeros) { for (byte b : scnData) { if (b != 0) { @@ -75,30 +102,30 @@ public class JELFRelocObject { } } if (zeros) { - scnType = ELF.SHT_NOBITS; + scnType = Elf64_Shdr.SHT_NOBITS; } } - int sectionId = elfContainer.createSection(c.getContainerName(), scnData, Elf_Type.ELF_T_BYTE, segmentSize, scnType, scnFlags, ELF.SHN_UNDEF, 0); - c.setSectionId(sectionId); - // Clear out code section data to allow for GC - c.clear(); + sect = createByteSection(sections, c.getContainerName(), + scnData, hasRelocs, segmentSize, + scnFlags, scnType); + c.setSectionId(sect.getSectionId()); } - private void createCodeSection(CodeContainer c) { - createByteSection(c, ELF.SHF_ALLOC | ELF.SHF_EXECINSTR); + private void createCodeSection(ArrayListsections, CodeContainer c) { + createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_EXECINSTR); } - private void createReadOnlySection(ReadOnlyDataContainer c) { - createByteSection(c, ELF.SHF_ALLOC); + private void createReadOnlySection(ArrayListsections, ReadOnlyDataContainer c) { + createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC); } - private void createReadWriteSection(ByteContainer c) { - createByteSection(c, ELF.SHF_ALLOC | ELF.SHF_WRITE); + private void createReadWriteSection(ArrayListsections, ByteContainer c) { + createByteSection(sections, c, Elf64_Shdr.SHF_ALLOC | Elf64_Shdr.SHF_WRITE); } /** - * Create an ELF relocatable object using jdk.tools.jaotc.jnilibelf API. + * Create an ELF relocatable object * * @param relocationTable * @param symbols @@ -106,145 +133,174 @@ public class JELFRelocObject { */ public void createELFRelocObject(Map> relocationTable, Collection symbols) throws IOException { // Allocate ELF Header - elfContainer.createELFHeader(ELF.ET_REL); + ElfHeader eh = new ElfHeader(); + + ArrayList sections = new ArrayList(); + + // Create the null section + createByteSection(sections, null, null, false, 1, 0, 0); // Create text section - createCodeSection(binContainer.getCodeContainer()); - createReadOnlySection(binContainer.getMetaspaceNamesContainer()); - createReadOnlySection(binContainer.getKlassesOffsetsContainer()); - createReadOnlySection(binContainer.getMethodsOffsetsContainer()); - createReadOnlySection(binContainer.getKlassesDependenciesContainer()); - createReadWriteSection(binContainer.getMetaspaceGotContainer()); - createReadWriteSection(binContainer.getMetadataGotContainer()); - createReadWriteSection(binContainer.getMethodStateContainer()); - createReadWriteSection(binContainer.getOopGotContainer()); - createReadWriteSection(binContainer.getMethodMetadataContainer()); - createReadOnlySection(binContainer.getStubsOffsetsContainer()); - createReadOnlySection(binContainer.getHeaderContainer().getContainer()); - createReadOnlySection(binContainer.getCodeSegmentsContainer()); - createReadOnlySection(binContainer.getConstantDataContainer()); - createReadOnlySection(binContainer.getConfigContainer()); + createCodeSection(sections, binContainer.getCodeContainer()); + createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer()); + createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer()); + createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer()); + createReadWriteSection(sections, binContainer.getMetaspaceGotContainer()); + createReadWriteSection(sections, binContainer.getMetadataGotContainer()); + createReadWriteSection(sections, binContainer.getMethodStateContainer()); + createReadWriteSection(sections, binContainer.getOopGotContainer()); + createReadWriteSection(sections, binContainer.getMethodMetadataContainer()); + createReadOnlySection(sections, binContainer.getStubsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer()); + createReadOnlySection(sections, binContainer.getCodeSegmentsContainer()); + createReadOnlySection(sections, binContainer.getConstantDataContainer()); + createReadOnlySection(sections, binContainer.getConfigContainer()); // createExternalLinkage(); - createCodeSection(binContainer.getExtLinkageContainer()); - createReadWriteSection(binContainer.getExtLinkageGOTContainer()); + createCodeSection(sections, binContainer.getExtLinkageContainer()); + createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer()); // Get ELF symbol data from BinaryContainer object's symbol tables - createELFSymbolTables(symbols); + ElfSymtab symtab = createELFSymbolTables(sections, symbols); // Create string table section and symbol table sections in - // that order since symtab section needs to set the index of strtab in sh_link field - int strTabSectionIndex = elfContainer.createSection(".strtab", elfContainer.getStrTabContent().getBytes(StandardCharsets.UTF_8), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, 0, ELF.SHN_UNDEF, 0); + // that order since symtab section needs to set the index of + // strtab in sh_link field + ElfSection strTabSection = createByteSection(sections, + ".strtab", + symtab.getStrtabArray(), + false, + 1, + 0, + Elf64_Shdr.SHT_STRTAB); - // Now create .symtab section with the symtab data constructed. On Linux, sh_link of symtab - // contains the index of string table its symbols reference and - // sh_info contains the index of first non-local symbol - int scnInfo = elfContainer.getFirstNonLocalSymbolIndex(); - int symTabSectionIndex = elfContainer.createSection(".symtab", getELFSymbolTableData(), Elf_Type.ELF_T_SYM, 8, ELF.SHT_SYMTAB, ELF.SHF_ALLOC, strTabSectionIndex, scnInfo); + // Now create .symtab section with the symtab data constructed. + // On Linux, sh_link of symtab contains the index of string table + // its symbols reference and sh_info contains the index of first + // non-local symbol + ElfSection symTabSection = createByteSection(sections, + ".symtab", + symtab.getSymtabArray(), + false, + 8, + 0, + Elf64_Shdr.SHT_SYMTAB); + symTabSection.setLink(strTabSection.getSectionId()); + symTabSection.setInfo(symtab.getNumLocalSyms()); - buildRelocations(relocationTable, symTabSectionIndex); + ElfRelocTable elfRelocTable = createElfRelocTable(sections, + relocationTable); + + createElfRelocSections(sections, elfRelocTable, symTabSection.getSectionId()); // Now, finally, after creating all sections, create shstrtab section - elfContainer.createSection(".shstrtab", elfContainer.getShStrTabContent().getBytes(StandardCharsets.UTF_8), Elf_Type.ELF_T_BYTE, 1, ELF.SHT_STRTAB, 0, ELF.SHN_UNDEF, 0); + ElfSection shStrTabSection = createByteSection(sections, + ".shstrtab", + null, + false, + 1, + 0, + Elf64_Shdr.SHT_STRTAB); + eh.setSectionStrNdx(shStrTabSection.getSectionId()); - // Run elf_update - elfContainer.elfUpdate(Elf_Cmd.ELF_C_NULL); + // Update all section offsets and the Elf header section offset + // Write the Header followed by the contents of each section + // and then the section structures (section table). + int file_offset = Elf64_Ehdr.totalsize; - // Run elfUpdate again to write it out. - elfContainer.elfUpdate(Elf_Cmd.ELF_C_WRITE); - // Finish ELF processing - elfContainer.elfEnd(); + // and round it up + file_offset = (file_offset + (sections.get(1).getDataAlign()-1)) & + ~((sections.get(1).getDataAlign()-1)); + + // Calc file offsets for section data skipping null section + for (int i = 1; i < sections.size(); i++) { + ElfSection sect = sections.get(i); + file_offset = (file_offset + (sect.getDataAlign()-1)) & + ~((sect.getDataAlign()-1)); + sect.setOffset(file_offset); + file_offset += sect.getSize(); + } + + // Align the section table + file_offset = (file_offset + (ElfSection.getShdrAlign()-1)) & + ~((ElfSection.getShdrAlign()-1)); + + // Update the Elf Header with the offset of the first Elf64_Shdr + // and the number of sections. + eh.setSectionOff(file_offset); + eh.setSectionNum(sections.size()); + + // Write out the Header + elfContainer.writeBytes(eh.getArray()); + + // Write out each section contents skipping null section + for (int i = 1; i < sections.size(); i++) { + ElfSection sect = sections.get(i); + elfContainer.writeBytes(sect.getDataArray(), sect.getDataAlign()); + } + + // Write out the section table + for (int i = 0; i < sections.size(); i++) { + ElfSection sect = sections.get(i); + elfContainer.writeBytes(sect.getArray(), ElfSection.getShdrAlign()); + } + + elfContainer.close(); } - - private void buildRelocations(Map> relocationTable, final int symTabSectionIndex) { - /* - * Create relocation sections. This needs to be done after symbol table sections were - * created since relocation entries will need indices of sections to which they apply. - */ - createELFRelocationTables(relocationTable); - createAllRelocationSections(new SymTabELFContainer(symTabSectionIndex)); - } - /** * Construct ELF symbol data from BinaryContainer object's symbol tables. Both dynamic ELF * symbol table and ELF symbol table are created from BinaryContainer's symbol info. * * @param symbols */ - private void createELFSymbolTables(Collection symbols) { + private ElfSymtab createELFSymbolTables(ArrayList sections, Collection symbols) { + ElfSymtab symtab = new ElfSymtab(); + // First, create the initial null symbol. This is a local symbol. - elfContainer.createELFSymbolEntry("", 0, 0, ELF.SHN_UNDEF, 0, 0, true); + symtab.addSymbolEntry("", (byte)0, (byte)0, Elf64_Shdr.SHN_UNDEF, 0, 0); // Now create ELF symbol entries for all symbols. for (Symbol symbol : symbols) { // Get the index of section this symbol is defined in. int secHdrIndex = symbol.getSection().getSectionId(); - boolean isLocal = (symbol.getBinding() == Binding.LOCAL); - ELFSymbol elfSymbol = elfContainer.createELFSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), secHdrIndex, symbol.getSize(), symbol.getOffset(), isLocal); - symbol.setElfSymbol(elfSymbol); + ElfSymbol elfSymbol = symtab.addSymbolEntry(symbol.getName(), getELFTypeOf(symbol), getELFBindOf(symbol), (byte)secHdrIndex, symbol.getOffset(), symbol.getSize()); + symbol.setNativeSymbol((NativeSymbol)elfSymbol); } + return (symtab); } - /** - * Construct ELF symbol data from BinaryContainer object's symbol tables. - * - * @return a byte array containing the symbol table - */ - private byte[] getELFSymbolTableData() { - final int entrySize = JNIELFTargetInfo.sizeOfSymtabEntry(); - - // First, add all local symbols. - List localSymbols = elfContainer.getLocalSymbols(); - List globalSymbols = elfContainer.getGlobalSymbols(); - - int localSymCount = localSymbols.size(); - int globalSymCount = globalSymbols.size(); - byte[] sectionDataArray = new byte[(localSymCount + globalSymCount) * entrySize]; - - for (int i = 0; i < localSymCount; i++) { - ELFSymbol symbol = localSymbols.get(i); - Pointer address = symbol.getAddress(); - address.copyBytesTo(sectionDataArray, entrySize, i * entrySize); - } - - // Next, add all global symbols. - - for (int i = 0; i < globalSymCount; i++) { - ELFSymbol symbol = globalSymbols.get(i); - Pointer address = symbol.getAddress(); - address.copyBytesTo(sectionDataArray, entrySize, (localSymCount + i) * entrySize); - } - - return sectionDataArray; - } - - private static int getELFTypeOf(Symbol sym) { + private static byte getELFTypeOf(Symbol sym) { Kind kind = sym.getKind(); if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) { - return ELF.STT_FUNC; + return Elf64_Sym.STT_FUNC; } else if (kind == Symbol.Kind.OBJECT) { - return ELF.STT_OBJECT; + return Elf64_Sym.STT_OBJECT; } - return ELF.STT_NOTYPE; + return Elf64_Sym.STT_NOTYPE; } - private static int getELFBindOf(Symbol sym) { + private static byte getELFBindOf(Symbol sym) { Binding binding = sym.getBinding(); if (binding == Symbol.Binding.GLOBAL) { - return ELF.STB_GLOBAL; + return Elf64_Sym.STB_GLOBAL; } - return ELF.STB_LOCAL; + return Elf64_Sym.STB_LOCAL; } /** - * Construct ELF relocation section data from BinaryContainer object's relocation tables. + * Construct a Elf relocation table from BinaryContainer object's relocation tables. * + * @param sections * @param relocationTable */ - private void createELFRelocationTables(Map> relocationTable) { + private ElfRelocTable createElfRelocTable(ArrayList sections, + Map> relocationTable) { + + ElfRelocTable elfRelocTable = new ElfRelocTable(sections.size()); /* - * For each of the symbols with associated relocation records, create an ELF relocation + * For each of the symbols with associated relocation records, create a Elf relocation * entry. */ for (Map.Entry> entry : relocationTable.entrySet()) { @@ -252,18 +308,26 @@ public class JELFRelocObject { Symbol symbol = entry.getKey(); for (Relocation reloc : relocs) { - createRelocation(symbol, reloc); + createRelocation(symbol, reloc, elfRelocTable); } } for (Map.Entry entry : binContainer.getUniqueRelocationTable().entrySet()) { - createRelocation(entry.getKey(), entry.getValue()); + createRelocation(entry.getKey(), entry.getValue(), elfRelocTable); } + + return (elfRelocTable); } - private void createRelocation(Symbol symbol, Relocation reloc) { + private void createRelocation(Symbol symbol, Relocation reloc, ElfRelocTable elfRelocTable) { RelocType relocType = reloc.getType(); + int elfRelocType = getELFRelocationType(relocType); + ElfSymbol sym = (ElfSymbol)symbol.getNativeSymbol(); + int symno = sym.getIndex(); + int sectindex = reloc.getSection().getSectionId(); + int offset = reloc.getOffset(); + int addend = 0; switch (relocType) { case FOREIGN_CALL_DIRECT: @@ -271,85 +335,89 @@ public class JELFRelocObject { case STUB_CALL_DIRECT: case FOREIGN_CALL_INDIRECT_GOT: { // Create relocation entry - int addend = -4; // Size in bytes of the patch location + // System.out.println("getELFRelocationType: PLT relocation type using X86_64_RELOC_BRANCH"); + addend = -4; // Size in bytes of the patch location // Relocation should be applied at the location after call operand - int offset = reloc.getOffset() + reloc.getSize() + addend; - elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol()); + offset = offset + reloc.getSize() + addend; break; } case FOREIGN_CALL_DIRECT_FAR: { // Create relocation entry - int addend = -8; // Size in bytes of the patch location + addend = -8; // Size in bytes of the patch location // Relocation should be applied at the location after call operand // 10 = 2 (jmp [r]) + 8 (imm64) - int offset = reloc.getOffset() + reloc.getSize() + addend - 2; - elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol()); + offset = offset + reloc.getSize() + addend - 2; break; } case FOREIGN_CALL_INDIRECT: case JAVA_CALL_INDIRECT: case STUB_CALL_INDIRECT: { // Do nothing. - break; + return; } case EXTERNAL_DATA_REFERENCE_FAR: { // Create relocation entry - int addend = -4; // Size of 32-bit address of the GOT + addend = -4; // Size of 32-bit address of the GOT /* * Relocation should be applied before the test instruction to the move instruction. - * reloc.getOffset() points to the test instruction after the instruction that loads + * offset points to the test instruction after the instruction that loads * the address of polling page. So set the offset appropriately. */ - int offset = reloc.getOffset() + addend; - elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol()); + offset = offset + addend; break; } case METASPACE_GOT_REFERENCE: case EXTERNAL_PLT_TO_GOT: case STATIC_STUB_TO_STATIC_METHOD: case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: { - int addend = -4; // Size of 32-bit address of the GOT + addend = -4; // Size of 32-bit address of the GOT /* - * Relocation should be applied before the test instruction to the move instruction. - * reloc.getOffset() points to the test instruction after the instruction that loads - * the address of polling page. So set the offset appropriately. + * Relocation should be applied before the test instruction to + * the move instruction. reloc.getOffset() points to the + * test instruction after the instruction that loads the + * address of polling page. So set the offset appropriately. */ - int offset = reloc.getOffset() + addend; - elfContainer.createELFRelocationEntry(reloc.getSection(), offset, elfRelocType, addend, symbol.getElfSymbol()); + offset = offset + addend; break; } case EXTERNAL_GOT_TO_PLT: case LOADTIME_ADDRESS: { // this is load time relocations - elfContainer.createELFRelocationEntry(reloc.getSection(), reloc.getOffset(), elfRelocType, 0, symbol.getElfSymbol()); break; } default: throw new InternalError("Unhandled relocation type: " + relocType); } + elfRelocTable.createRelocationEntry(sectindex, offset, symno, elfRelocType, addend); } - // TODO: Populate the mapping of RelocType to ELF relocation types private static int getELFRelocationType(RelocType relocType) { int elfRelocType = 0; // R__NONE if #define'd to 0 for all values of ARCH - switch (JNIELFTargetInfo.getELFArch()) { - case ELF.EM_X64_64: + switch (ElfTargetInfo.getElfArch()) { + case Elf64_Ehdr.EM_X86_64: // Return R_X86_64_* entries based on relocType - if (relocType == RelocType.FOREIGN_CALL_DIRECT || relocType == RelocType.JAVA_CALL_DIRECT || relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PLT32; + if (relocType == RelocType.FOREIGN_CALL_DIRECT || + relocType == RelocType.JAVA_CALL_DIRECT || + relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { + elfRelocType = Elf64_Rela.R_X86_64_PLT32; } else if (relocType == RelocType.STUB_CALL_DIRECT) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PC32; + elfRelocType = Elf64_Rela.R_X86_64_PC32; } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_64; - } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || relocType == RelocType.JAVA_CALL_INDIRECT || relocType == RelocType.STUB_CALL_INDIRECT) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_NONE; + elfRelocType = Elf64_Rela.R_X86_64_64; + } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || + relocType == RelocType.JAVA_CALL_INDIRECT || + relocType == RelocType.STUB_CALL_INDIRECT) { + elfRelocType = Elf64_Rela.R_X86_64_NONE; } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_GOTPCREL; - } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || relocType == RelocType.EXTERNAL_PLT_TO_GOT || relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD || - relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_PC32; - } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || relocType == RelocType.LOADTIME_ADDRESS) { - elfRelocType = JNIELFRelocation.X86_64.R_X86_64_64; + elfRelocType = Elf64_Rela.R_X86_64_GOTPCREL; + } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || + relocType == RelocType.EXTERNAL_PLT_TO_GOT || + relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD || + relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) { + elfRelocType = Elf64_Rela.R_X86_64_PC32; + } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || + relocType == RelocType.LOADTIME_ADDRESS) { + elfRelocType = Elf64_Rela.R_X86_64_64; } else { assert false : "Unhandled relocation type: " + relocType; } @@ -360,61 +428,27 @@ public class JELFRelocObject { return elfRelocType; } - private void createAllRelocationSections(ELFContainer symtab) { - for (Map.Entry> entry : elfContainer.getRelocTables().entrySet()) { - createRelocationSection(entry.getKey(), entry.getValue(), symtab); - } - } + private void createElfRelocSections(ArrayList sections, + ElfRelocTable elfRelocTable, + int symtabsectidx) { - private void createRelocationSection(ELFContainer container, ArrayList relocations, ELFContainer symtab) { - String secName = container.getContainerName(); - int entrySize = JNIELFTargetInfo.sizeOfRelocEntry(); - int numEntries = relocations.size(); - byte[] sectionDataBytes = new byte[numEntries * entrySize]; + // Grab count before we create new sections + int count = sections.size(); - for (int index = 0; index < relocations.size(); index++) { - Pointer entry = relocations.get(index); - entry.copyBytesTo(sectionDataBytes, entrySize, index * entrySize); - } - String fullSecName; - // If relocDat is non-null create section - if (sectionDataBytes.length > 0) { - int scnType; - Elf_Type dataType; - if (JNIELFTargetInfo.createReloca() == 0) { - scnType = ELF.SHT_REL; - dataType = Elf_Type.ELF_T_REL; - fullSecName = ".rel" + secName; - } else { - scnType = ELF.SHT_RELA; - dataType = Elf_Type.ELF_T_RELA; - fullSecName = ".rela" + secName; + for (int i = 0; i < count; i++) { + if (elfRelocTable.getNumRelocs(i) > 0) { + ElfSection sect = sections.get(i); + String relname = ".rela" + sect.getName(); + ElfSection relocSection = createByteSection(sections, + relname, + elfRelocTable.getRelocData(i), + false, + 8, + 0, + Elf64_Shdr.SHT_RELA); + relocSection.setLink(symtabsectidx); + relocSection.setInfo(sect.getSectionId()); } - // assert compareBytes(relocData.toByteArray(), sectionDataBytes) : "******* Bad array - // copy"; - // sh_link holds the index of section header of symbol table associated with this - // relocation table. - // sh_info holds the index of section header to which this relocation table applies - // to. - elfContainer.createSection(fullSecName, sectionDataBytes, dataType, 8, scnType, ELF.SHF_ALLOC, symtab.getSectionId(), container.getSectionId()); - } - } - - private static class SymTabELFContainer implements ELFContainer { - private final int symTabSectionIndex; - - public SymTabELFContainer(int symTabSectionIndex) { - this.symTabSectionIndex = symTabSectionIndex; - } - - @Override - public String getContainerName() { - return ".symtab"; - } - - @Override - public int getSectionId() { - return symTabSectionIndex; } } } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java new file mode 100644 index 00000000000..39941757672 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/JMachORelocObject.java @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2017, 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. + */ + +/* + * + * File Layout generated by JMachORelocObject + * + * MachO Header + * Load Commands + * LC_SEGMENT_64 + * - Sections + * LC_VERSION_MIN_MAX + * LC_SYMTAB + * LC_DYSYMTAB + * Section Data + * Relocation entries + * Symbol table + * + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import jdk.tools.jaotc.binformat.BinaryContainer; +import jdk.tools.jaotc.binformat.ByteContainer; +import jdk.tools.jaotc.binformat.CodeContainer; +import jdk.tools.jaotc.binformat.ReadOnlyDataContainer; +import jdk.tools.jaotc.binformat.Relocation; +import jdk.tools.jaotc.binformat.Relocation.RelocType; +import jdk.tools.jaotc.binformat.Symbol; +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.Symbol.Binding; +import jdk.tools.jaotc.binformat.Symbol.Kind; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.section_64; +import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64; +import jdk.tools.jaotc.binformat.macho.MachO.segment_command_64; +import jdk.tools.jaotc.binformat.macho.MachO.version_min_command; +import jdk.tools.jaotc.binformat.macho.MachO.symtab_command; +import jdk.tools.jaotc.binformat.macho.MachO.dysymtab_command; +import jdk.tools.jaotc.binformat.macho.MachO.nlist_64; +import jdk.tools.jaotc.binformat.macho.MachO.reloc_info; +import jdk.tools.jaotc.binformat.macho.MachOContainer; +import jdk.tools.jaotc.binformat.macho.MachOTargetInfo; +import jdk.tools.jaotc.binformat.macho.MachOSymtab; +import jdk.tools.jaotc.binformat.macho.MachORelocTable; + +public class JMachORelocObject { + + private final BinaryContainer binContainer; + + private final MachOContainer machoContainer; + + private final int segmentSize; + + public JMachORelocObject(BinaryContainer binContainer, String outputFileName) { + this.binContainer = binContainer; + this.machoContainer = new MachOContainer(outputFileName); + this.segmentSize = binContainer.getCodeSegmentSize(); + } + + private void createByteSection(ArrayListsections, + ByteContainer c, String sectName, String segName, int scnFlags) { + + if (c.getByteArray().length == 0) { + // System.out.println("Skipping creation of " + sectName + " section, no data\n"); + } + + MachOSection sect = new MachOSection(sectName, + segName, + c.getByteArray(), + scnFlags, + c.hasRelocations(), + segmentSize); + // Add this section to our list + sections.add(sect); + + // Record the section Id (0 relative) + c.setSectionId(sections.size()-1); + + // TODO: Clear out code section data to allow for GC + // c.clear(); + } + + private void createCodeSection(ArrayListsections, CodeContainer c) { + createByteSection(sections, c, /*c.getContainerName()*/ "__text", "__TEXT", + section_64.S_ATTR_PURE_INSTRUCTIONS| + section_64.S_ATTR_SOME_INSTRUCTIONS); + } + + private void createReadOnlySection(ArrayListsections, ReadOnlyDataContainer c) { + createByteSection(sections, c, c.getContainerName(), "__TEXT", + section_64.S_ATTR_SOME_INSTRUCTIONS); + } + + private void createReadWriteSection(ArrayListsections, ByteContainer c) { + createByteSection(sections, c, c.getContainerName(), "__DATA", section_64.S_REGULAR); + } + + /** + * Create an MachO relocatable object + * + * @param relocationTable + * @param symbols + * @throws IOException throws {@code IOException} as a result of file system access failures. + */ + public void createMachORelocObject(Map> relocationTable, Collection symbols) throws IOException { + // Allocate MachO Header + // with 4 load commands + // LC_SEGMENT_64 + // LC_VERSION_MIN_MACOSX + // LC_SYMTAB + // LC_DYSYMTAB + + MachOHeader mh = new MachOHeader(); + + ArrayList sections = new ArrayList(); + + // Create Sections contained in the main Segment LC_SEGMENT_64 + + createCodeSection(sections, binContainer.getCodeContainer()); + createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer()); + createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer()); + createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer()); + createReadWriteSection(sections, binContainer.getMetaspaceGotContainer()); + createReadWriteSection(sections, binContainer.getMetadataGotContainer()); + createReadWriteSection(sections, binContainer.getMethodStateContainer()); + createReadWriteSection(sections, binContainer.getOopGotContainer()); + createReadWriteSection(sections, binContainer.getMethodMetadataContainer()); + createReadOnlySection(sections, binContainer.getStubsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer()); + createReadOnlySection(sections, binContainer.getCodeSegmentsContainer()); + createReadOnlySection(sections, binContainer.getConstantDataContainer()); + createReadOnlySection(sections, binContainer.getConfigContainer()); + + // createExternalLinkage(); + + createCodeSection(sections, binContainer.getExtLinkageContainer()); + createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer()); + // Update the Header sizeofcmds size. + // This doesn't include the Header struct size + mh.setCmdSizes(4, segment_command_64.totalsize + + (section_64.totalsize * sections.size()) + + version_min_command.totalsize + + symtab_command.totalsize + + dysymtab_command.totalsize); + + // Initialize file offset for data past commands + int file_offset = mach_header_64.totalsize + mh.getCmdSize(); + // and round it up + file_offset = (file_offset + (sections.get(0).getAlign()-1)) & ~((sections.get(0).getAlign()-1)); + long address = 0; + int segment_offset = file_offset; + + for (int i = 0; i < sections.size(); i++) { + MachOSection sect = sections.get(i); + file_offset = (file_offset + (sect.getAlign()-1)) & ~((sect.getAlign()-1)); + address = (address + (sect.getAlign()-1)) & ~((sect.getAlign()-1)); + sect.setOffset(file_offset); + sect.setAddr(address); + file_offset += sect.getSize(); + address += sect.getSize(); + } + + // File size for Segment data + int segment_size = file_offset - segment_offset; + + // Create the LC_SEGMENT_64 Segment which contains the MachOSections + MachOSegment seg = new MachOSegment(segment_command_64.totalsize + + (section_64.totalsize * sections.size()), + segment_offset, + segment_size, + sections.size()); + + + MachOVersion vers = new MachOVersion(); + + // Get symbol data from BinaryContainer object's symbol tables + MachOSymtab symtab = createMachOSymbolTables(sections, symbols); + + // Create LC_DYSYMTAB command + MachODySymtab dysymtab = new MachODySymtab(symtab.getNumLocalSyms(), + symtab.getNumGlobalSyms(), + symtab.getNumUndefSyms()); + + // Create the Relocation Tables + MachORelocTable machORelocs = createMachORelocTable(sections, relocationTable, symtab); + // Calculate file offset for relocation data + file_offset = (file_offset + (machORelocs.getAlign()-1)) & ~((machORelocs.getAlign()-1)); + + // Update relocation sizing information in each section + for (int i = 0; i < sections.size(); i++) { + MachOSection sect = sections.get(i); + if (sect.hasRelocations()) { + int nreloc = machORelocs.getNumRelocs(i); + sect.setReloff(file_offset); + sect.setRelcount(nreloc); + file_offset += (nreloc * reloc_info.totalsize); + } + } + + // Calculate and set file offset for symbol table data + file_offset = (file_offset + (symtab.getAlign()-1)) & ~((symtab.getAlign()-1)); + symtab.setOffset(file_offset); + + + // Write Out Header + machoContainer.writeBytes(mh.getArray()); + // Write out first Segment + machoContainer.writeBytes(seg.getArray()); + // Write out sections within first Segment + for (int i = 0; i < sections.size(); i++) { + MachOSection sect = sections.get(i); + machoContainer.writeBytes(sect.getArray()); + } + + // Write out LC_VERSION_MIN_MACOSX command + machoContainer.writeBytes(vers.getArray()); + + // Write out LC_SYMTAB command + symtab.calcSizes(); + machoContainer.writeBytes(symtab.getCmdArray()); + + // Write out LC_DYSYMTAB command + machoContainer.writeBytes(dysymtab.getArray()); + + // Write out data associated with each Section + for (int i = 0; i < sections.size(); i++) { + MachOSection sect = sections.get(i); + machoContainer.writeBytes(sect.getDataArray(), sect.getAlign()); + } + + // Write out the relocation tables for all sections + for (int i = 0; i < sections.size(); i++) { + if (machORelocs.getNumRelocs(i) > 0) + machoContainer.writeBytes(machORelocs.getRelocData(i), machORelocs.getAlign()); + } + + // Write out data associated with LC_SYMTAB + machoContainer.writeBytes(symtab.getDataArray(), symtab.getAlign()); + + machoContainer.close(); + } + + /** + * Construct MachO symbol data from BinaryContainer object's symbol tables. Both dynamic MachO + * symbol table and MachO symbol table are created from BinaryContainer's symbol info. + * + * @param symbols + * @param symtab + */ + private MachOSymtab createMachOSymbolTables(ArrayListsections, + Collection symbols) { + MachOSymtab symtab = new MachOSymtab(); + // First, create the initial null symbol. This is a local symbol. + symtab.addSymbolEntry("", (byte)nlist_64.N_UNDF, (byte)0, (long)0); + + // Now create MachO symbol entries for all symbols. + for (Symbol symbol : symbols) { + int sectionId = symbol.getSection().getSectionId(); + + // Symbol offsets are relative to the section memory addr + long sectionAddr = sections.get(sectionId).getAddr(); + + MachOSymbol machoSymbol = symtab.addSymbolEntry(symbol.getName(), + getMachOTypeOf(symbol), + (byte)sectionId, + symbol.getOffset() + sectionAddr); + symbol.setNativeSymbol((NativeSymbol)machoSymbol); + } + + // Now that all symbols are enterred, update the + // symbol indexes. This is necessary since they will + // be reordered based on local, global and undefined. + symtab.updateIndexes(); + + return (symtab); + } + + private static byte getMachOTypeOf(Symbol sym) { + Kind kind = sym.getKind(); + byte type = nlist_64.N_UNDF; + + // Global or Local + if (sym.getBinding() == Symbol.Binding.GLOBAL) + type = nlist_64.N_EXT; + + // If Function or Data, add section type + if (kind == Symbol.Kind.NATIVE_FUNCTION || + kind == Symbol.Kind.JAVA_FUNCTION || + kind == Symbol.Kind.OBJECT) { + type |= (nlist_64.N_SECT); + } + + return (type); + } + + /** + * Construct a MachO relocation table from BinaryContainer object's relocation tables. + * + * @param sections + * @param relocationTable + * @param symtab + */ + private MachORelocTable createMachORelocTable(ArrayList sections, + Map> relocationTable, + MachOSymtab symtab) { + + MachORelocTable machORelocTable = new MachORelocTable(sections.size()); + /* + * For each of the symbols with associated relocation records, create a MachO relocation + * entry. + */ + for (Map.Entry> entry : relocationTable.entrySet()) { + List relocs = entry.getValue(); + Symbol symbol = entry.getKey(); + + for (Relocation reloc : relocs) { + createRelocation(symbol, reloc, machORelocTable); + } + } + + for (Map.Entry entry : binContainer.getUniqueRelocationTable().entrySet()) { + createRelocation(entry.getKey(), entry.getValue(), machORelocTable); + } + + return (machORelocTable); + } + + private void createRelocation(Symbol symbol, Relocation reloc, MachORelocTable machORelocTable) { + RelocType relocType = reloc.getType(); + + int machORelocType = getMachORelocationType(relocType); + MachOSymbol sym = (MachOSymbol)symbol.getNativeSymbol(); + int symno = sym.getIndex(); + int sectindex = reloc.getSection().getSectionId(); + int offset = reloc.getOffset(); + int pcrel = 0; + int length = 0; + int isextern = 1; + +/* + System.out.println("reloctype: " + relocType + " size is " + + reloc.getSize() + " offset is " + offset + + " Section Index is " + (sectindex) + + " Symbol Index is " + symno + + " Symbol Name is " + symbol.getName() + "\n"); +*/ + + switch (relocType) { + case FOREIGN_CALL_DIRECT: + case JAVA_CALL_DIRECT: + case STUB_CALL_DIRECT: + case FOREIGN_CALL_INDIRECT_GOT: { + // Create relocation entry + // System.out.println("getMachORelocationType: PLT relocation type using X86_64_RELOC_BRANCH"); + int addend = -4; // Size in bytes of the patch location + // Relocation should be applied at the location after call operand + offset = offset + reloc.getSize() + addend; + pcrel = 1; length = 2; + break; + } + case FOREIGN_CALL_DIRECT_FAR: { + // Create relocation entry + int addend = -8; // Size in bytes of the patch location + // Relocation should be applied at the location after call operand + // 10 = 2 (jmp [r]) + 8 (imm64) + offset = offset + reloc.getSize() + addend - 2; + pcrel = 0; length = 3; + break; + } + case FOREIGN_CALL_INDIRECT: + case JAVA_CALL_INDIRECT: + case STUB_CALL_INDIRECT: { + // Do nothing. + return; + } + case EXTERNAL_DATA_REFERENCE_FAR: { + // Create relocation entry + int addend = -4; // Size of 32-bit address of the GOT + /* + * Relocation should be applied before the test instruction to the move instruction. + * offset points to the test instruction after the instruction that loads + * the address of polling page. So set the offset appropriately. + */ + offset = offset + addend; + pcrel = 0; length = 2; + break; + } + case METASPACE_GOT_REFERENCE: + case EXTERNAL_PLT_TO_GOT: + case STATIC_STUB_TO_STATIC_METHOD: + case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: { + int addend = -4; // Size of 32-bit address of the GOT + /* + * Relocation should be applied before the test instruction to + * the move instruction. reloc.getOffset() points to the + * test instruction after the instruction that loads the + * address of polling page. So set the offset appropriately. + */ + offset = offset + addend; + pcrel = 1; length = 2; + break; + } + case EXTERNAL_GOT_TO_PLT: + case LOADTIME_ADDRESS: { + // this is load time relocations + pcrel = 0; length = 3; + break; + } + default: + throw new InternalError("Unhandled relocation type: " + relocType); + } + machORelocTable.createRelocationEntry(sectindex, offset, symno, + pcrel, length, isextern, + machORelocType); + } + + private static int getMachORelocationType(RelocType relocType) { + int machORelocType = 0; + switch (MachOTargetInfo.getMachOArch()) { + case mach_header_64.CPU_TYPE_X86_64: + // Return X86_64_RELOC_* entries based on relocType + if (relocType == RelocType.FOREIGN_CALL_DIRECT || relocType == RelocType.JAVA_CALL_DIRECT || relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { + machORelocType = reloc_info.X86_64_RELOC_BRANCH; + } else if (relocType == RelocType.STUB_CALL_DIRECT) { + machORelocType = reloc_info.X86_64_RELOC_BRANCH; + } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) { + machORelocType = reloc_info.X86_64_RELOC_UNSIGNED; + } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || relocType == RelocType.JAVA_CALL_INDIRECT || relocType == RelocType.STUB_CALL_INDIRECT) { + machORelocType = reloc_info.X86_64_RELOC_NONE; + } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) { + machORelocType = reloc_info.X86_64_RELOC_GOT; + } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || relocType == RelocType.EXTERNAL_PLT_TO_GOT || relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD || + relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) { + machORelocType = reloc_info.X86_64_RELOC_BRANCH; + } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || relocType == RelocType.LOADTIME_ADDRESS) { + machORelocType = reloc_info.X86_64_RELOC_UNSIGNED; + } else { + assert false : "Unhandled relocation type: " + relocType; + } + break; + default: + System.out.println("Relocation Type mapping: Unhandled architecture"); + } + return machORelocType; + } +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java new file mode 100644 index 00000000000..752723f25dc --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachO.java @@ -0,0 +1,307 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +/** + * + * Support for the creation of Mach-o Object files. + * Current support is limited to 64 bit x86_64. + * + * File Format Overview: + * + * mach_header + * load_commands + * Typical Mac OSX 64-bit object files have these 4 load_commands + * (LC_SEGMENT_64, LC_SYMTAB, LC_VERSIN_MIN_MACOSX, LC_DYSYMTAB) + * Segments corresponding to load_commands + * (which each include multiple Sections) + */ + +public class MachO { + + /** + * mach_header_64 structure defines + */ + public enum mach_header_64 { + magic( 0, 4), + cputype( 4, 4), + cpusubtype( 8, 4), + filetype(12, 4), + ncmds(16, 4), + sizeofcmds(20, 4), + flags(24, 4), + reserved(28, 4); + + public final int off; + public final int sz; + + mach_header_64(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 32; + + /** + * mach_header_64 defines + */ + public static final int MH_MAGIC = 0xfeedface; + public static final int MH_MAGIC_64 = 0xfeedfacf; + public static final int MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000; + + /** + * filetype + */ + public static final int MH_OBJECT = 0x1; + + /** + * cputype + */ + public static final int CPU_TYPE_ANY = -1; + public static final int CPU_ARCH_ABI64 = 0x1000000; + public static final int CPU_TYPE_X86_64 = 0x1000007; + public static final int CPU_TYPE_ARM64 = 0x100000c; + /** + * cpusubtype + */ + public static final int CPU_SUBTYPE_I386_ALL = 3; + public static final int CPU_SUBTYPE_ARM64_ALL = 0; + public static final int CPU_SUBTYPE_LITTLE_ENDIAN = 0; + public static final int CPU_SUBTYPE_BIG_ENDIAN = 1; + + } + + /** + * segment_command_64 structure defines + */ + public enum segment_command_64 { + cmd( 0, 4), + cmdsize( 4, 4), + segname( 8,16), + vmaddr(24, 8), + vmsize(32, 8), + fileoff(40, 8), + filesize(48, 8), + maxprot(56, 4), + initprot(60, 4), + nsects(64, 4), + flags(68, 4); + + public final int off; + public final int sz; + + segment_command_64(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 72; + + public static final int LC_SEGMENT_64 = 0x19; + } + + /** + * section_64 structure defines + */ + public enum section_64 { + sectname( 0,16), + segname(16,16), + addr(32, 8), + size(40, 8), + offset(48, 4), + align(52, 4), + reloff(56, 4), + nreloc(60, 4), + flags(64, 4), + reserved1(68, 4), + reserved2(72, 4), + reserved3(76, 4); + + public final int off; + public final int sz; + + section_64(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 80; + + public static int S_REGULAR = 0x0; + public static int S_CSTRING_LITERALS = 0x2; + public static int S_ATTR_PURE_INSTRUCTIONS = 0x80000000; + public static int S_ATTR_SOME_INSTRUCTIONS = 0x400; + } + + /** + * version_min_command structure defines + */ + public enum version_min_command { + cmd( 0, 4), + cmdsize( 4, 4), + version( 8, 4), + sdk(12, 4); + + public final int off; + public final int sz; + + version_min_command(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 16; + + public static final int LC_VERSION_MIN_MACOSX = 0x24; + public static final int LC_VERSION_MIN_IPHONEOS = 0x25; + } + + /** + * symtab_command structure defines + */ + public enum symtab_command { + cmd( 0, 4), + cmdsize( 4, 4), + symoff( 8, 4), + nsyms(12, 4), + stroff(16, 4), + strsize(20, 4); + + public final int off; + public final int sz; + + symtab_command(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 24; + + public static final int LC_SYMTAB = 0x2; + } + + /** + * Symbol table entry definitions + * + * nlist_64 structure defines + */ + public enum nlist_64 { + n_strx( 0, 4), + n_type( 4, 1), + n_sect( 5, 1), + n_desc( 6, 2), + n_value( 8, 8); + + public final int off; + public final int sz; + + nlist_64(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 16; + + public static final int N_EXT = 0x1; + public static final int N_TYPE = 0xe; + public static final int N_UNDF = 0x0; + public static final int N_SECT = 0xe; + } + + /** + * dysymtab_command structure defines + */ + public enum dysymtab_command { + cmd( 0, 4), + cmdsize( 4, 4), + ilocalsym( 8, 4), + nlocalsym(12, 4), + iextdefsym(16, 4), + nextdefsym(20, 4), + iundefsym(24, 4), + nundefsym(28, 4), + tocoff(32, 4), + ntoc(36, 4), + modtaboff(40, 4), + nmodtab(44, 4), + extrefsymoff(48, 4), + nextrefsyms(52, 4), + indirectsymoff(56, 4), + nindirectsyms(60, 4), + extreloff(64, 4), + nextrel(68, 4), + locreloff(72, 4), + nlocrel(76, 4); + + public final int off; + public final int sz; + + dysymtab_command(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 80; + + public static final int LC_DYSYMTAB = 0xb; + } + + /** + * relocation_info structure defines + */ + public enum reloc_info { + r_address( 0, 4), + r_relocinfo( 4, 4); + + public final int off; + public final int sz; + + reloc_info(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 8; + + public static final int REL_SYMNUM_MASK = 0xffffff; + public static final int REL_SYMNUM_SHIFT = 0x0; + public static final int REL_PCREL_MASK = 0x1; + public static final int REL_PCREL_SHIFT = 0x18; + public static final int REL_LENGTH_MASK = 0x3; + public static final int REL_LENGTH_SHIFT = 0x19; + public static final int REL_EXTERN_MASK = 0x1; + public static final int REL_EXTERN_SHIFT = 0x1b; + public static final int REL_TYPE_MASK = 0xf; + public static final int REL_TYPE_SHIFT = 0x1c; + + /* reloc_type_x86_64 defines */ + + public static final int X86_64_RELOC_NONE = 0x0; + public static final int X86_64_RELOC_BRANCH = 0x2; + public static final int X86_64_RELOC_GOT = 0x4; + public static final int X86_64_RELOC_GOT_LOAD = 0x3; + public static final int X86_64_RELOC_SIGNED = 0x1; + public static final int X86_64_RELOC_UNSIGNED = 0x0; + } +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java new file mode 100644 index 00000000000..14b75387277 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOByteBuffer.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.macho.MachOTargetInfo; +import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64; + +public class MachOByteBuffer { + + public static ByteBuffer allocate(int size) { + ByteBuffer buf = ByteBuffer.allocate(size); + if (MachOTargetInfo.getMachOEndian() == + MachO.mach_header_64.CPU_SUBTYPE_LITTLE_ENDIAN) + buf.order(ByteOrder.LITTLE_ENDIAN); + else + buf.order(ByteOrder.BIG_ENDIAN); + return (buf); + } + +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java new file mode 100644 index 00000000000..bcb46c368c7 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOContainer.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.io.File; +import java.io.FileOutputStream; + +public class MachOContainer { + + File outputFile; + FileOutputStream outputStream; + long fileOffset; + + public MachOContainer(String fileName) { + String baseName; + + outputFile = new File(fileName); + if (outputFile.exists()) { + outputFile.delete(); + } + + try { + outputStream = new FileOutputStream(outputFile); + } catch (Exception e) { + System.out.println("MachOContainer: Can't create file " + fileName); + } + fileOffset = 0; + } + + public void close() { + try { + outputStream.close(); + } catch (Exception e) { + System.out.println("MachOContainer: close failed"); + } + } + + public void writeBytes(byte [] bytes) { + try { + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("MachOContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } + + // Write bytes to output file with up front alignment padding + public void writeBytes(byte [] bytes, int alignment) { + try { + // Pad to alignment + while ((fileOffset & (long)(alignment-1)) != 0) { + outputStream.write(0); + fileOffset++; + } + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("MachOContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java new file mode 100644 index 00000000000..4ede3869087 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachODySymtab.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.dysymtab_command; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachODySymtab { + ByteBuffer dysymtab; + + public MachODySymtab(int nlocal, int nglobal, int nundef) { + dysymtab = MachOByteBuffer.allocate(dysymtab_command.totalsize); + + dysymtab.putInt(dysymtab_command.cmd.off, dysymtab_command.LC_DYSYMTAB); + dysymtab.putInt(dysymtab_command.cmdsize.off, dysymtab_command.totalsize); + dysymtab.putInt(dysymtab_command.ilocalsym.off, 0); + dysymtab.putInt(dysymtab_command.nlocalsym.off, nlocal); + dysymtab.putInt(dysymtab_command.iextdefsym.off, nlocal); + dysymtab.putInt(dysymtab_command.nextdefsym.off, nglobal); + dysymtab.putInt(dysymtab_command.iundefsym.off, nlocal+nglobal); + dysymtab.putInt(dysymtab_command.nundefsym.off, nundef); + } + + public byte[] getArray() { + return dysymtab.array(); + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java new file mode 100644 index 00000000000..ae50f0186d9 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOHeader.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64; +import jdk.tools.jaotc.binformat.macho.MachOTargetInfo; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOHeader { + ByteBuffer header; + + public MachOHeader() { + header = MachOByteBuffer.allocate(mach_header_64.totalsize); + + header.putInt(mach_header_64.magic.off, mach_header_64.MH_MAGIC_64); + header.putInt(mach_header_64.cputype.off, MachOTargetInfo.getMachOArch()); + header.putInt(mach_header_64.cpusubtype.off, MachOTargetInfo.getMachOSubArch()); + header.putInt(mach_header_64.flags.off, 0x2000); + header.putInt(mach_header_64.filetype.off, mach_header_64.MH_OBJECT); + } + + public void setCmdSizes(int ncmds, int sizeofcmds) { + header.putInt(mach_header_64.ncmds.off, ncmds); + header.putInt(mach_header_64.sizeofcmds.off, sizeofcmds); + } + + public int getCmdSize() { + return (header.getInt(mach_header_64.sizeofcmds.off)); + } + + public byte[] getArray() { + return header.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java new file mode 100644 index 00000000000..f32cfda3d78 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocEntry.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.reloc_info; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachORelocEntry { + ByteBuffer entry; + + public MachORelocEntry(int offset, + int symno, + int pcrel, + int length, + int isextern, + int type) { + + entry = MachOByteBuffer.allocate(reloc_info.totalsize); + + entry.putInt(reloc_info.r_address.off, offset); + + // Encode and store the relocation entry bitfields + entry.putInt(reloc_info.r_relocinfo.off, + ((symno & reloc_info.REL_SYMNUM_MASK) + << reloc_info.REL_SYMNUM_SHIFT) | + ((pcrel & reloc_info.REL_PCREL_MASK) + << reloc_info.REL_PCREL_SHIFT) | + ((length & reloc_info.REL_LENGTH_MASK) + << reloc_info.REL_LENGTH_SHIFT) | + ((isextern & reloc_info.REL_EXTERN_MASK) + << reloc_info.REL_EXTERN_SHIFT) | + ((type & reloc_info.REL_TYPE_MASK) + << reloc_info.REL_TYPE_SHIFT)); + } + + public byte[] getArray() { + return entry.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java new file mode 100644 index 00000000000..196ae4615a8 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachORelocTable.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.util.ArrayList; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachORelocEntry; +import jdk.tools.jaotc.binformat.macho.MachOTargetInfo; +import jdk.tools.jaotc.binformat.macho.MachO.reloc_info; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachORelocTable { + ArrayList> relocEntries; + int fileOffset; + + public MachORelocTable(int numsects) { + relocEntries = new ArrayList>(numsects); + for (int i = 0; i < numsects; i++) + relocEntries.add(new ArrayList()); + } + + public void createRelocationEntry(int sectindex, + int offset, + int symno, + int pcrel, + int length, + int isextern, + int type) { + + MachORelocEntry entry = new MachORelocEntry(offset, + symno, + pcrel, + length, + isextern, + type); + relocEntries.get(sectindex).add(entry); + } + + public int getAlign() { + return (4); + } + + public int getNumRelocs(int section_index) { + return relocEntries.get(section_index).size(); + } + + // Return the relocation entries for a single section + // or null if no entries added to section + public byte [] getRelocData(int section_index) { + ArrayList entryList = relocEntries.get(section_index); + + if (entryList.size() == 0) + return null; + + ByteBuffer relocData = MachOByteBuffer.allocate(entryList.size() * reloc_info.totalsize); + + // Copy each entry to a single ByteBuffer + for (int i = 0; i < entryList.size(); i++) { + MachORelocEntry entry = entryList.get(i); + relocData.put(entry.getArray()); + } + + return (relocData.array()); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java new file mode 100644 index 00000000000..61b814a795a --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSection.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.section_64; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOSection { + ByteBuffer section; + byte [] data; + boolean hasrelocations; + + public MachOSection(String sectName, String segName, byte [] sectData, int sectFlags, boolean hasRelocations, int align) { + section = MachOByteBuffer.allocate(section_64.totalsize); + + // TODO: Hotspot uses long section names. + // They are getting truncated. + // Is this a problem?? + byte[] sectNameBytes = sectName.getBytes(); + int sectNameMax = section_64.sectname.sz < sectNameBytes.length ? + section_64.sectname.sz : sectNameBytes.length; + + for (int i = 0; i < sectNameMax; i++) + section.put(section_64.sectname.off+i, sectNameBytes[i]); + + byte[] segNameBytes = segName.getBytes(); + int segNameMax = section_64.segname.sz < segNameBytes.length ? + section_64.segname.sz : segNameBytes.length; + + for (int i = 0; i < segNameMax; i++) + section.put(section_64.segname.off+i, segNameBytes[i]); + + section.putLong(section_64.size.off, sectData.length); + + section.putInt(section_64.align.off, + 31 - Integer.numberOfLeadingZeros(align)); + + section.putInt(section_64.flags.off, sectFlags); + + data = sectData; + + hasrelocations = hasRelocations; + } + + public long getSize() { + return section.getLong(section_64.size.off); + } + + public int getAlign() { + return (1 << section.getInt(section_64.align.off)); + } + + public byte[] getArray() { + return section.array(); + } + + public byte[] getDataArray() { + return data; + } + + public void setAddr(long addr) { + section.putLong(section_64.addr.off, addr); + } + + public long getAddr() { + return (section.getLong(section_64.addr.off)); + } + + public void setOffset(int offset) { + section.putInt(section_64.offset.off, offset); + } + + public int getOffset() { + return (section.getInt(section_64.offset.off)); + } + + public void setReloff(int offset) { + section.putInt(section_64.reloff.off, offset); + } + + public void setRelcount(int count) { + section.putInt(section_64.nreloc.off, count); + } + + public boolean hasRelocations() { + return hasrelocations; + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java new file mode 100644 index 00000000000..3f588512783 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSegment.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.segment_command_64; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOSegment { + ByteBuffer segment; + + public MachOSegment(int size, int fileoff, int filesize, int nsects) { + segment = MachOByteBuffer.allocate(segment_command_64.totalsize); + + segment.putInt(segment_command_64.cmd.off, segment_command_64.LC_SEGMENT_64); + segment.putInt(segment_command_64.cmdsize.off, size); + segment.putInt(segment_command_64.maxprot.off, 7); + segment.putInt(segment_command_64.initprot.off, 7); + segment.putInt(segment_command_64.nsects.off, nsects); + segment.putInt(segment_command_64.flags.off, 0); + segment.putLong(segment_command_64.vmaddr.off, 0); + segment.putLong(segment_command_64.vmsize.off, filesize); + segment.putLong(segment_command_64.fileoff.off, fileoff); + segment.putLong(segment_command_64.filesize.off, filesize); + } + + public byte[] getArray() { + return segment.array(); + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java new file mode 100644 index 00000000000..7c4444d9cab --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymbol.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.nlist_64; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOSymbol extends NativeSymbol { + ByteBuffer sym; + + public MachOSymbol(int symbolindex, int strindex, byte type, byte sectindex, long offset) { + super(symbolindex); + sym = MachOByteBuffer.allocate(nlist_64.totalsize); + + sym.putInt(nlist_64.n_strx.off, strindex); + sym.put(nlist_64.n_type.off, type); + // Section indexes start at 1 but we manage the index internally + // as 0 relative + sym.put(nlist_64.n_sect.off, (byte)(sectindex+1)); + sym.putChar(nlist_64.n_desc.off, (char )0); + sym.putLong(nlist_64.n_value.off, offset); + } + + public byte[] getArray() { + return sym.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java new file mode 100644 index 00000000000..be24bc83cd8 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOSymtab.java @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.symtab_command; +import jdk.tools.jaotc.binformat.macho.MachO.nlist_64; +import jdk.tools.jaotc.binformat.macho.MachOSymbol; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOSymtab { + + /** + * ByteBuffer holding the LC_SYMTAB command contents + */ + ByteBuffer symtabCmd; + + /** + * ByteBuffer holding the symbol table entries and strings + */ + ByteBuffer symtabData; + + int symtabDataSize; + + ArrayListlocalSymbols = new ArrayList(); + ArrayListglobalSymbols = new ArrayList(); + ArrayListundefSymbols = new ArrayList(); + + /** + * number of symbols added + */ + int symbolCount; + + /** + * String holding symbol table strings + */ + private StringBuilder strTabContent = new StringBuilder(); + + /** + * Keeps track of bytes in string table since strTabContent.length() + * is number of chars, not bytes. + */ + private int strTabNrOfBytes = 0; + + public MachOSymtab() { + symtabCmd = MachOByteBuffer.allocate(symtab_command.totalsize); + + symtabCmd.putInt(symtab_command.cmd.off, symtab_command.LC_SYMTAB); + symtabCmd.putInt(symtab_command.cmdsize.off, symtab_command.totalsize); + + symbolCount = 0; + + } + + public int getAlign() { + return (4); + } + + public MachOSymbol addSymbolEntry(String name, byte type, byte secHdrIndex, long offset) { + // Get the current symbol index and append symbol name to string table. + int index; + MachOSymbol sym; + + if (name.isEmpty()) { + index = 0; + strTabContent.append('\0'); + strTabNrOfBytes += 1; + sym = new MachOSymbol(symbolCount, index, type, secHdrIndex, offset); + localSymbols.add(sym); + } else { + // We can't trust strTabContent.length() since that is + // chars (UTF16), keep track of bytes on our own. + index = strTabNrOfBytes; + strTabContent.append("_").append(name).append('\0'); + // + 1 for null, + 1 for "_" + strTabNrOfBytes += (name.getBytes().length + 1 + 1); + + sym = new MachOSymbol(symbolCount, index, type, secHdrIndex, offset); + switch (type) { + case nlist_64.N_EXT: + undefSymbols.add(sym); + break; + case nlist_64.N_SECT: + case nlist_64.N_UNDF: // null symbol + localSymbols.add(sym); + break; + case nlist_64.N_SECT|nlist_64.N_EXT: + globalSymbols.add(sym); + break; + default: + System.out.println("Unsupported Symbol type " + type); + break; + } + } + symbolCount++; + return (sym); + } + + public void setOffset(int symoff) { + symtabCmd.putInt(symtab_command.symoff.off, symoff); + } + + // Update the symbol indexes once all symbols have been added. + // This is required since we'll be reordering the symbols in the + // file to be in the order of Local, global and Undefined. + public void updateIndexes() { + int index = 0; + + // Update the local symbol indexes + for (int i = 0; i < localSymbols.size(); i++ ) { + MachOSymbol sym = localSymbols.get(i); + sym.setIndex(index++); + } + + // Update the global symbol indexes + for (int i = 0; i < globalSymbols.size(); i++ ) { + MachOSymbol sym = globalSymbols.get(i); + sym.setIndex(index++); + } + + // Update the undefined symbol indexes + for (int i = index; i < undefSymbols.size(); i++ ) { + MachOSymbol sym = undefSymbols.get(i); + sym.setIndex(index++); + } + } + + // Update LC_SYMTAB command fields based on the number of symbols added + // return the file size taken up by symbol table entries and strings + public int calcSizes() { + int stroff; + + stroff = symtabCmd.getInt(symtab_command.symoff.off) + (nlist_64.totalsize * symbolCount); + symtabCmd.putInt(symtab_command.nsyms.off, symbolCount); + symtabCmd.putInt(symtab_command.stroff.off, stroff); + symtabCmd.putInt(symtab_command.strsize.off, strTabNrOfBytes); + symtabDataSize = (nlist_64.totalsize * symbolCount) + strTabNrOfBytes; + + return (symtabDataSize); + } + + public int getNumLocalSyms() { return localSymbols.size(); } + public int getNumGlobalSyms() { return globalSymbols.size(); } + public int getNumUndefSyms() { return undefSymbols.size(); } + + public byte[] getCmdArray() { + return symtabCmd.array(); + } + + // Create a single byte array that contains the symbol table entries + // and string table + public byte[] getDataArray() { + int index = 0; + symtabData = MachOByteBuffer.allocate(symtabDataSize); + byte [] retarray; + + // Add the local symbols + for (int i = 0; i < localSymbols.size(); i++ ) { + MachOSymbol sym = localSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + // Add the global symbols + for (int i = 0; i < globalSymbols.size(); i++ ) { + MachOSymbol sym = globalSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + // Add the undefined symbols + for (int i = 0; i < undefSymbols.size(); i++ ) { + MachOSymbol sym = undefSymbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + + // Add the stringtable + byte [] strs = strTabContent.toString().getBytes(); + symtabData.put(strs); + + retarray = symtabData.array(); + + return (retarray); + } +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java new file mode 100644 index 00000000000..1a0a199d499 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOTargetInfo.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.mach_header_64; + +/** + * Class that abstracts MACH-O target details. + * + */ +public class MachOTargetInfo { + /** + * Target architecture and subtype. + */ + private static final int arch; + private static final int subarch; + + /** + * Architecture endian-ness. + */ + private static final int endian = mach_header_64.CPU_SUBTYPE_LITTLE_ENDIAN; + + /** + * Target OS string. + */ + private static final String osName; + + static { + // Find the target arch details + String archStr = System.getProperty("os.arch").toLowerCase(); + + if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) { + System.out.println("Only Little Endian byte order supported!"); + } + + if (archStr.equals("amd64") || archStr.equals("x86_64")) { + arch = mach_header_64.CPU_TYPE_X86_64; + subarch = mach_header_64.CPU_SUBTYPE_I386_ALL; + } else { + System.out.println("Unsupported architecture " + archStr); + arch = mach_header_64.CPU_TYPE_ANY; + subarch = 0; + } + + osName = System.getProperty("os.name").toLowerCase(); + } + + public static int getMachOArch() { + return arch; + } + + public static int getMachOSubArch() { + return subarch; + } + + public static int getMachOEndian() { + return endian; + } + + public static String getOsName() { + return osName; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java new file mode 100644 index 00000000000..57475aeb0eb --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/macho/MachOVersion.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.macho; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.macho.MachO; +import jdk.tools.jaotc.binformat.macho.MachO.version_min_command; +import jdk.tools.jaotc.binformat.macho.MachOByteBuffer; + +public class MachOVersion { + ByteBuffer version; + + public MachOVersion() { + version = MachOByteBuffer.allocate(version_min_command.totalsize); + + version.putInt(version_min_command.cmd.off, version_min_command.LC_VERSION_MIN_MACOSX); + version.putInt(version_min_command.cmdsize.off, version_min_command.totalsize); + version.putInt(version_min_command.version.off, (10 << 16) | (10 << 8)); /* MacOSX 10.10 */ + version.putInt(version_min_command.sdk.off, 0); /* N/A SDK */ + } + + public byte[] getArray() { + return version.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java new file mode 100644 index 00000000000..89c853e5ac9 --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/JPECoffRelocObject.java @@ -0,0 +1,425 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import jdk.tools.jaotc.binformat.Container; +import jdk.tools.jaotc.binformat.BinaryContainer; +import jdk.tools.jaotc.binformat.ByteContainer; +import jdk.tools.jaotc.binformat.CodeContainer; +import jdk.tools.jaotc.binformat.ReadOnlyDataContainer; +import jdk.tools.jaotc.binformat.Relocation; +import jdk.tools.jaotc.binformat.Relocation.RelocType; +import jdk.tools.jaotc.binformat.Symbol; +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.Symbol.Binding; +import jdk.tools.jaotc.binformat.Symbol.Kind; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoffSymbol; +import jdk.tools.jaotc.binformat.pecoff.PECoffTargetInfo; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SECTION_HEADER; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION; + +public class JPECoffRelocObject { + + private final BinaryContainer binContainer; + + private final PECoffContainer pecoffContainer; + + private final int segmentSize; + + public JPECoffRelocObject(BinaryContainer binContainer, String outputFileName, String aotVersion) { + this.binContainer = binContainer; + this.pecoffContainer = new PECoffContainer(outputFileName, aotVersion); + this.segmentSize = binContainer.getCodeSegmentSize(); + if (segmentSize != 64) { + System.out.println("binContainer alignment size not 64 bytes, update JPECoffRelocObject"); + } + } + + private PECoffSection createByteSection(ArrayListsections, + String sectName, + byte [] scnData, + boolean hasRelocs, + int scnFlags) { + + PECoffSection sect = new PECoffSection(sectName, + scnData, + scnFlags, + hasRelocs, + sections.size()); + // Add this section to our list + sections.add(sect); + + return (sect); + } + + private void createByteSection(ArrayListsections, + ByteContainer c, int scnFlags) { + PECoffSection sect; + boolean hasRelocs = c.hasRelocations(); + byte[] scnData = c.getByteArray(); + + sect = createByteSection(sections, c.getContainerName(), + scnData, hasRelocs, + scnFlags); + + c.setSectionId(sect.getSectionId()); + } + + private void createCodeSection(ArrayListsections, CodeContainer c) { + createByteSection(sections, c, IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | + IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_EXECUTE | + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_64BYTES | + IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_CODE); + } + + private void createReadOnlySection(ArrayListsections, ReadOnlyDataContainer c) { + createByteSection(sections, c, IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_64BYTES | + IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA); + } + + private void createReadWriteSection(ArrayListsections, ByteContainer c) { + int scnFlags = IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_READ | + IMAGE_SECTION_HEADER.IMAGE_SCN_MEM_WRITE | + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_64BYTES; + + if (c.getByteArray().length > 0) + scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_INITIALIZED_DATA; + else + scnFlags |= IMAGE_SECTION_HEADER.IMAGE_SCN_CNT_UNINITIALIZED_DATA; + + createByteSection(sections, c, scnFlags); + } + + /** + * Create an PECoff relocatable object + * + * @param relocationTable + * @param symbols + * @throws IOException throws {@code IOException} as a result of file system access failures. + */ + public void createPECoffRelocObject(Map> relocationTable, Collection symbols) throws IOException { + ArrayList sections = new ArrayList(); + + // Create text section + createCodeSection(sections, binContainer.getCodeContainer()); + createReadOnlySection(sections, binContainer.getMetaspaceNamesContainer()); + createReadOnlySection(sections, binContainer.getKlassesOffsetsContainer()); + createReadOnlySection(sections, binContainer.getMethodsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getKlassesDependenciesContainer()); + createReadWriteSection(sections, binContainer.getMetaspaceGotContainer()); + createReadWriteSection(sections, binContainer.getMetadataGotContainer()); + createReadWriteSection(sections, binContainer.getMethodStateContainer()); + createReadWriteSection(sections, binContainer.getOopGotContainer()); + createReadWriteSection(sections, binContainer.getMethodMetadataContainer()); + createReadOnlySection(sections, binContainer.getStubsOffsetsContainer()); + createReadOnlySection(sections, binContainer.getHeaderContainer().getContainer()); + createReadOnlySection(sections, binContainer.getCodeSegmentsContainer()); + createReadOnlySection(sections, binContainer.getConstantDataContainer()); + createReadOnlySection(sections, binContainer.getConfigContainer()); + + // createExternalLinkage(); + + createCodeSection(sections, binContainer.getExtLinkageContainer()); + createReadWriteSection(sections, binContainer.getExtLinkageGOTContainer()); + + // Allocate PECoff Header + PECoffHeader header = new PECoffHeader(); + + // Get PECoff symbol data from BinaryContainer object's symbol tables + PECoffSymtab symtab = createPECoffSymbolTables(sections, symbols); + + // Add Linker Directives Section + createByteSection(sections, ".drectve", + symtab.getDirectiveArray(), false, + IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_INFO | + IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_REMOVE | + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_1BYTES); + + // Create the Relocation Tables + PECoffRelocTable pecoffRelocs = createPECoffRelocTable(sections, relocationTable); + + // File Output Order + // + // HEADER (Need address of Symbol Table + symbol count) + // SECTIONS (Need pointer to Section Data, Relocation Table) + // DIRECTIVES + // SYMBOL TABLE + // SYMBOLS + // SECTION DATA + // RELOCATION TABLE + + // Calculate Offset for Symbol table + int file_offset = IMAGE_FILE_HEADER.totalsize + + (IMAGE_SECTION_HEADER.totalsize*sections.size()); + + // Update Header fields + header.setSectionCount(sections.size()); + header.setSymbolCount(symtab.getSymtabCount()); + header.setSymbolOff(file_offset); + + // Calculate file offset for first section + file_offset += ((symtab.getSymtabCount() * IMAGE_SYMBOL.totalsize) + + symtab.getStrtabSize()); + // And round it up + file_offset = (file_offset + (sections.get(0).getDataAlign()-1)) & + ~((sections.get(0).getDataAlign()-1)); + + // Calc file offsets for section data + for (int i = 0; i < sections.size(); i++) { + PECoffSection sect = sections.get(i); + file_offset = (file_offset + (sect.getDataAlign()-1)) & + ~((sect.getDataAlign()-1)); + sect.setOffset(file_offset); + file_offset += sect.getSize(); + } + + // Update relocation sizing information in each section + for (int i = 0; i < sections.size(); i++) { + PECoffSection sect = sections.get(i); + if (sect.hasRelocations()) { + int nreloc = pecoffRelocs.getNumRelocs(i); + sect.setReloff(file_offset); + sect.setRelcount(nreloc); + // extended relocations add an addition entry + if (nreloc > 0xFFFF) nreloc++; + file_offset += (nreloc * IMAGE_RELOCATION.totalsize); + } + } + + // Write out the Header + pecoffContainer.writeBytes(header.getArray()); + + // Write out the section table + for (int i = 0; i < sections.size(); i++) { + PECoffSection sect = sections.get(i); + pecoffContainer.writeBytes(sect.getArray(), PECoffSection.getShdrAlign()); + } + + // Write out the symbol table and string table + pecoffContainer.writeBytes(symtab.getSymtabArray(), 4); + pecoffContainer.writeBytes(symtab.getStrtabArray(), 1); + + // Write out each section contents + for (int i = 0; i < sections.size(); i++) { + PECoffSection sect = sections.get(i); + pecoffContainer.writeBytes(sect.getDataArray(), sect.getDataAlign()); + } + + // Write out Relocation Tables + for (int i = 0; i < sections.size(); i++) { + if (pecoffRelocs.getNumRelocs(i) > 0) { + pecoffContainer.writeBytes(pecoffRelocs.getRelocData(i)); + } + } + pecoffContainer.close(); + } + + /** + * Construct PECoff symbol data from BinaryContainer object's symbol tables. Both dynamic PECoff + * symbol table and PECoff symbol table are created from BinaryContainer's symbol info. + * + * @param symbols + */ + private PECoffSymtab createPECoffSymbolTables(ArrayList sections, Collection symbols) { + PECoffSymtab symtab = new PECoffSymtab(); + + // First, create the initial null symbol. This is a local symbol. + // symtab.addSymbolEntry("", (byte)0, (byte)0, (byte)0, 0, 0); + + // Now create PECoff symbol entries for all symbols. + for (Symbol symbol : symbols) { + // Get the index of section this symbol is defined in. + int secHdrIndex = symbol.getSection().getSectionId(); + PECoffSymbol pecoffSymbol = symtab.addSymbolEntry(symbol.getName(), getPECoffTypeOf(symbol), getPECoffClassOf(symbol), (byte)secHdrIndex, symbol.getOffset(), symbol.getSize()); + symbol.setNativeSymbol((NativeSymbol)pecoffSymbol); + } + return (symtab); + } + + private static byte getPECoffTypeOf(Symbol sym) { + Kind kind = sym.getKind(); + if (kind == Symbol.Kind.NATIVE_FUNCTION || kind == Symbol.Kind.JAVA_FUNCTION) { + return IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION; + } + return IMAGE_SYMBOL.IMAGE_SYM_DTYPE_NONE; + } + + private static byte getPECoffClassOf(Symbol sym) { + Binding binding = sym.getBinding(); + if (binding == Symbol.Binding.GLOBAL) { + return IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL; + } + return IMAGE_SYMBOL.IMAGE_SYM_CLASS_STATIC; + } + + /** + * Construct a PECoff relocation table from BinaryContainer object's relocation tables. + * + * @param sections + * @param relocationTable + */ + private PECoffRelocTable createPECoffRelocTable(ArrayList sections, + Map> relocationTable) { + + PECoffRelocTable pecoffRelocTable = new PECoffRelocTable(sections.size()); + /* + * For each of the symbols with associated relocation records, create a PECoff relocation + * entry. + */ + for (Map.Entry> entry : relocationTable.entrySet()) { + List relocs = entry.getValue(); + Symbol symbol = entry.getKey(); + + for (Relocation reloc : relocs) { + createRelocation(symbol, reloc, pecoffRelocTable); + } + } + + for (Map.Entry entry : binContainer.getUniqueRelocationTable().entrySet()) { + createRelocation(entry.getKey(), entry.getValue(), pecoffRelocTable); + } + + return (pecoffRelocTable); + } + + private void createRelocation(Symbol symbol, Relocation reloc, PECoffRelocTable pecoffRelocTable) { + RelocType relocType = reloc.getType(); + + int pecoffRelocType = getPECoffRelocationType(relocType); + PECoffSymbol sym = (PECoffSymbol)symbol.getNativeSymbol(); + int symno = sym.getIndex(); + int sectindex = reloc.getSection().getSectionId(); + int offset = reloc.getOffset(); + int addend = 0; + + switch (relocType) { + case FOREIGN_CALL_DIRECT: + case JAVA_CALL_DIRECT: + case STUB_CALL_DIRECT: + case FOREIGN_CALL_INDIRECT_GOT: { + // Create relocation entry + addend = -4; // Size in bytes of the patch location + // Relocation should be applied at the location after call operand + offset = offset + reloc.getSize() + addend; + break; + } + case FOREIGN_CALL_DIRECT_FAR: { + // Create relocation entry + addend = -8; // Size in bytes of the patch location + // Relocation should be applied at the location after call operand + // 10 = 2 (jmp [r]) + 8 (imm64) + offset = offset + reloc.getSize() + addend - 2; + break; + } + case FOREIGN_CALL_INDIRECT: + case JAVA_CALL_INDIRECT: + case STUB_CALL_INDIRECT: { + // Do nothing. + return; + } + case EXTERNAL_DATA_REFERENCE_FAR: { + // Create relocation entry + addend = -4; // Size of 32-bit address of the GOT + /* + * Relocation should be applied before the test instruction to the move instruction. + * offset points to the test instruction after the instruction that loads + * the address of polling page. So set the offset appropriately. + */ + offset = offset + addend; + break; + } + case METASPACE_GOT_REFERENCE: + case EXTERNAL_PLT_TO_GOT: + case STATIC_STUB_TO_STATIC_METHOD: + case STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT: { + addend = -4; // Size of 32-bit address of the GOT + /* + * Relocation should be applied before the test instruction to + * the move instruction. reloc.getOffset() points to the + * test instruction after the instruction that loads the + * address of polling page. So set the offset appropriately. + */ + offset = offset + addend; + break; + } + case EXTERNAL_GOT_TO_PLT: + case LOADTIME_ADDRESS: { + // this is load time relocations + break; + } + default: + throw new InternalError("Unhandled relocation type: " + relocType); + } + pecoffRelocTable.createRelocationEntry(sectindex, offset, symno, pecoffRelocType); + } + + // Return IMAGE_RELOCATION Type based on relocType + private static int getPECoffRelocationType(RelocType relocType) { + int pecoffRelocType = 0; // R__NONE if #define'd to 0 for all values of ARCH + switch (PECoffTargetInfo.getPECoffArch()) { + case IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64: + if (relocType == RelocType.FOREIGN_CALL_DIRECT || + relocType == RelocType.JAVA_CALL_DIRECT || + relocType == RelocType.FOREIGN_CALL_INDIRECT_GOT) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32; + } else if (relocType == RelocType.STUB_CALL_DIRECT) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32; + } else if (relocType == RelocType.FOREIGN_CALL_DIRECT_FAR) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64; + } else if (relocType == RelocType.FOREIGN_CALL_INDIRECT || + relocType == RelocType.JAVA_CALL_INDIRECT || + relocType == RelocType.STUB_CALL_INDIRECT) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ABSOLUTE; + } else if ((relocType == RelocType.EXTERNAL_DATA_REFERENCE_FAR)) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32; + } else if (relocType == RelocType.METASPACE_GOT_REFERENCE || + relocType == RelocType.EXTERNAL_PLT_TO_GOT || + relocType == RelocType.STATIC_STUB_TO_STATIC_METHOD || + relocType == RelocType.STATIC_STUB_TO_HOTSPOT_LINKAGE_GOT) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_REL32; + } else if (relocType == RelocType.EXTERNAL_GOT_TO_PLT || + relocType == RelocType.LOADTIME_ADDRESS) { + pecoffRelocType = IMAGE_RELOCATION.IMAGE_REL_AMD64_ADDR64; + } else { + assert false : "Unhandled relocation type: " + relocType; + } + break; + default: + System.out.println("Relocation Type mapping: Unhandled architecture"); + } + return pecoffRelocType; + } +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java new file mode 100644 index 00000000000..f71b2a7dd7c --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoff.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +/** + * + * Support for the creation of Coff files. + * Current support is limited to 64 bit x86_64. + * + */ + +public class PECoff { + + /** + * IMAGE_FILE_HEADER structure defines + */ + public enum IMAGE_FILE_HEADER { + Machine( 0, 2), + NumberOfSections( 2, 2), + TimeDateStamp( 4, 4), + PointerToSymbolTable( 8, 4), + NumberOfSymbols(12, 4), + SizeOfOptionalHeader(16, 2), + Characteristics(18, 2); + + public final int off; + public final int sz; + + IMAGE_FILE_HEADER(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 20; + + /** + * IMAGE_FILE_HEADER defines + */ + + /** + * Machine + */ + public static final char IMAGE_FILE_MACHINE_UNKNOWN = 0x0; + public static final char IMAGE_FILE_MACHINE_AMD64 = 0x8664; + + } + + /** + * IMAGE_SECTION_HEADER structure defines + */ + public enum IMAGE_SECTION_HEADER { + Name( 0, 8), + PhysicalAddress( 8, 4), + VirtualSize( 8, 4), + VirtualAddress(12, 4), + SizeOfRawData(16, 4), + PointerToRawData(20, 4), + PointerToRelocations(24, 4), + PointerToLinenumbers(28, 4), + NumberOfRelocations(32, 2), + NumberOfLinenumbers(34, 2), + Characteristics(36, 4); + + public final int off; + public final int sz; + + IMAGE_SECTION_HEADER(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 40; + + /** + * IMAGE_SECTION_HEADER defines + */ + + /** + * Characteristics + */ + public static final int IMAGE_SCN_CNT_CODE = 0x20; + public static final int IMAGE_SCN_CNT_INITIALIZED_DATA = 0x40; + public static final int IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x80; + public static final int IMAGE_SCN_LNK_COMDAT = 0x1000; + public static final int IMAGE_SCN_LNK_INFO = 0x200; + public static final int IMAGE_SCN_LNK_REMOVE = 0x800; + + public static final int IMAGE_SCN_ALIGN_1BYTES = 0x100000; + public static final int IMAGE_SCN_ALIGN_2BYTES = 0x200000; + public static final int IMAGE_SCN_ALIGN_4BYTES = 0x300000; + public static final int IMAGE_SCN_ALIGN_8BYTES = 0x400000; + public static final int IMAGE_SCN_ALIGN_16BYTES = 0x500000; + public static final int IMAGE_SCN_ALIGN_32BYTES = 0x600000; + public static final int IMAGE_SCN_ALIGN_64BYTES = 0x700000; + public static final int IMAGE_SCN_ALIGN_MASK = 0xf00000; + public static final int IMAGE_SCN_ALIGN_SHIFT = 20; + + public static final int IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000; + + public static final int IMAGE_SCN_MEM_SHARED = 0x10000000; + public static final int IMAGE_SCN_MEM_EXECUTE = 0x20000000; + public static final int IMAGE_SCN_MEM_READ = 0x40000000; + public static final int IMAGE_SCN_MEM_WRITE = 0x80000000; + + } + + /** + * Symbol table entry definitions + * + * IMAGE_SYMBOL structure defines + */ + public enum IMAGE_SYMBOL { + ShortName( 0, 8), + Short( 0, 4), + Long( 4, 4), + Value( 8, 4), + SectionNumber(12, 2), + Type(14, 2), + StorageClass(16, 1), + NumberOfAuxSymbols(17, 1); + + public final int off; + public final int sz; + + IMAGE_SYMBOL(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 18; + + /** + * Type + */ + public static final int IMAGE_SYM_DTYPE_NONE = 0x0; + public static final int IMAGE_SYM_DTYPE_FUNCTION = 0x20; + + /** + * StorageClass + */ + public static final int IMAGE_SYM_CLASS_NULL = 0x0; + public static final int IMAGE_SYM_CLASS_EXTERNAL = 0x2; + public static final int IMAGE_SYM_CLASS_STATIC = 0x3; + public static final int IMAGE_SYM_CLASS_LABEL = 0x6; + + } + + /** + * IMAGE_RELOCATION structure defines + */ + public enum IMAGE_RELOCATION { + VirtualAddress( 0, 4), + SymbolTableIndex( 4, 4), + Type( 8, 2); + + public final int off; + public final int sz; + + IMAGE_RELOCATION(int offset, int size) { + this.off = offset; + this.sz = size; + } + + public static int totalsize = 10; + + /** + * Relocation types + */ + public static final int IMAGE_REL_AMD64_ABSOLUTE = 0x0; + public static final int IMAGE_REL_AMD64_ADDR32 = 0x2; + public static final int IMAGE_REL_AMD64_ADDR64 = 0x1; + public static final int IMAGE_REL_AMD64_REL32 = 0x4; + public static final int IMAGE_REL_AMD64_REL32_1 = 0x5; + public static final int IMAGE_REL_AMD64_REL32_2 = 0x6; + public static final int IMAGE_REL_AMD64_REL32_3 = 0x7; + public static final int IMAGE_REL_AMD64_REL32_4 = 0x8; + public static final int IMAGE_REL_AMD64_REL32_5 = 0x9; + + } + +} diff --git a/hotspot/test/compiler/cpuflags/predicate/AESSupportPredicate.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java similarity index 70% rename from hotspot/test/compiler/cpuflags/predicate/AESSupportPredicate.java rename to hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java index c2ac3e24316..e212c6b64d7 100644 --- a/hotspot/test/compiler/cpuflags/predicate/AESSupportPredicate.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffByteBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -21,18 +21,18 @@ * questions. */ -package compiler.cpuflags.predicate; +package jdk.tools.jaotc.binformat.pecoff; -import sun.hotspot.cpuinfo.CPUInfo; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; -import java.util.function.BooleanSupplier; +public class PECoffByteBuffer { -public class AESSupportPredicate implements BooleanSupplier { - - private static final String AES = "aes"; - - @Override - public boolean getAsBoolean() { - return CPUInfo.getFeatures().contains(AES); + public static ByteBuffer allocate(int size) { + ByteBuffer buf = ByteBuffer.allocate(size); + // Only support Little Endian on Windows + buf.order(ByteOrder.LITTLE_ENDIAN); + return (buf); } + } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java new file mode 100644 index 00000000000..75158fd219f --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffContainer.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.io.File; +import java.io.FileOutputStream; + +public class PECoffContainer { + + File outputFile; + FileOutputStream outputStream; + long fileOffset; + + public PECoffContainer(String fileName, String aotVersion) { + String baseName; + + outputFile = new File(fileName); + if (outputFile.exists()) { + outputFile.delete(); + } + + try { + outputStream = new FileOutputStream(outputFile); + } catch (Exception e) { + System.out.println("PECoffContainer: Can't create file " + fileName); + } + fileOffset = 0; + } + + public void close() { + try { + outputStream.close(); + } catch (Exception e) { + System.out.println("PECoffContainer: close failed"); + } + } + + public void writeBytes(byte [] bytes) { + if (bytes == null) return; + try { + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("PECoffContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } + + // Write bytes to output file with up front alignment padding + public void writeBytes(byte [] bytes, int alignment) { + if (bytes == null) return; + try { + // Pad to alignment + while ((fileOffset & (long)(alignment-1)) != 0) { + outputStream.write(0); + fileOffset++; + } + outputStream.write(bytes); + } catch (Exception e) { + System.out.println("PECoffContainer: writeBytes failed"); + } + fileOffset += bytes.length; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java new file mode 100644 index 00000000000..7d2c84f841d --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffHeader.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER; +import jdk.tools.jaotc.binformat.pecoff.PECoffTargetInfo; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffHeader { + ByteBuffer header; + + public PECoffHeader() { + header = PECoffByteBuffer.allocate(IMAGE_FILE_HEADER.totalsize); + + header.putChar(IMAGE_FILE_HEADER.Machine.off, IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64); + header.putInt(IMAGE_FILE_HEADER.TimeDateStamp.off, (int)(System.currentTimeMillis()/1000)); + header.putInt(IMAGE_FILE_HEADER.PointerToSymbolTable.off, 0); + header.putInt(IMAGE_FILE_HEADER.NumberOfSymbols.off, 0); + header.putChar(IMAGE_FILE_HEADER.SizeOfOptionalHeader.off, (char)0); + header.putChar(IMAGE_FILE_HEADER.Characteristics.off, (char)0); + + } + + // Update header with the number of total sections + public void setSectionCount(int count) { + header.putChar(IMAGE_FILE_HEADER.NumberOfSections.off, (char)count); + } + + // Update header with the number of total symbols + public void setSymbolCount(int count) { + header.putInt(IMAGE_FILE_HEADER.NumberOfSymbols.off, count); + } + + // Update header with the offset of symbol table + public void setSymbolOff(int offset) { + header.putInt(IMAGE_FILE_HEADER.PointerToSymbolTable.off, offset); + } + + public byte[] getArray() { + return header.array(); + } +} + diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArraySet.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java similarity index 56% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArraySet.java rename to hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java index cf4a8824b6d..11284dc77a4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArraySet.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -20,38 +20,30 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.core.common.util; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; +package jdk.tools.jaotc.binformat.pecoff; -/** - * Mimic a set implementation with an ArrayList. Beneficial for small sets (compared to - * {@link HashSet}). - */ -public class ArraySet extends ArrayList implements Set { - private static final long serialVersionUID = 4476957522387436654L; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; - public ArraySet() { - super(); +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffRelocEntry { + ByteBuffer entry; + + public PECoffRelocEntry(int offset, int symno, int type) { + + entry = PECoffByteBuffer.allocate(IMAGE_RELOCATION.totalsize); + + entry.putInt(IMAGE_RELOCATION.VirtualAddress.off, offset); + entry.putInt(IMAGE_RELOCATION.SymbolTableIndex.off, symno); + entry.putChar(IMAGE_RELOCATION.Type.off, (char)type); } - public ArraySet(int i) { - super(i); - } - - public ArraySet(Collection c) { - super(c); - } - - @Override - public boolean add(E e) { - // avoid duplicated entries - if (contains(e)) { - return false; - } - return super.add(e); + public byte[] getArray() { + return entry.array(); } } + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java new file mode 100644 index 00000000000..c51b9e8710a --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffRelocTable.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.util.ArrayList; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_RELOCATION; +import jdk.tools.jaotc.binformat.pecoff.PECoffRelocEntry; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffRelocTable { + ArrayList> relocEntries; + + public PECoffRelocTable(int numsects) { + relocEntries = new ArrayList>(numsects); + for (int i = 0; i < numsects; i++) + relocEntries.add(new ArrayList()); + } + + public void createRelocationEntry(int sectindex, + int offset, + int symno, + int type) { + + PECoffRelocEntry entry = new PECoffRelocEntry(offset, + symno, + type); + relocEntries.get(sectindex).add(entry); + } + + public int getAlign() { return (4); } + + public int getNumRelocs(int section_index) { + return relocEntries.get(section_index).size(); + } + + // Return the relocation entries for a single section + // or null if no entries added to section + public byte [] getRelocData(int section_index) { + ArrayList entryList = relocEntries.get(section_index); + int entryCount = entryList.size(); + int allocCount = entryCount; + + if (entryCount == 0) + return null; + + if (entryCount > 0xFFFF) + allocCount++; + + ByteBuffer relocData = PECoffByteBuffer.allocate(allocCount * IMAGE_RELOCATION.totalsize); + + // If number of relocs exceeds 65K, add the real size + // in a dummy first reloc entry + if (entryCount > 0xFFFF) { + PECoffRelocEntry entry = new PECoffRelocEntry(allocCount, 0, 0); + relocData.put(entry.getArray()); + } + + // Copy each entry to a single ByteBuffer + for (int i = 0; i < entryCount; i++) { + PECoffRelocEntry entry = entryList.get(i); + relocData.put(entry.getArray()); + } + + return (relocData.array()); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java new file mode 100644 index 00000000000..0e05fdb830a --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSection.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SECTION_HEADER; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffSection { + ByteBuffer section; + byte [] data; + boolean hasrelocations; + int sectionIndex; + int align; + + public PECoffSection(String sectName, byte [] sectData, int sectFlags, + boolean hasRelocations, int sectIndex) { + + section = PECoffByteBuffer.allocate(IMAGE_SECTION_HEADER.totalsize); + + // bug: If JVM.oop.got section is empty, VM exits since JVM.oop.got + // symbol ends up as external forwarded reference. + if (sectData.length == 0) sectData = new byte[8]; + + // Copy only Max allowed bytes to Section Entry + byte [] Name = sectName.getBytes(); + int max = Name.length <= IMAGE_SECTION_HEADER.Name.sz ? + Name.length : IMAGE_SECTION_HEADER.Name.sz; + + section.put(Name, IMAGE_SECTION_HEADER.Name.off, max); + + section.putInt(IMAGE_SECTION_HEADER.VirtualSize.off, 0); + section.putInt(IMAGE_SECTION_HEADER.VirtualAddress.off, 0); + section.putInt(IMAGE_SECTION_HEADER.SizeOfRawData.off, sectData.length); + section.putInt(IMAGE_SECTION_HEADER.PointerToLinenumbers.off, 0); + section.putChar(IMAGE_SECTION_HEADER.NumberOfLinenumbers.off, (char)0); + + section.putInt(IMAGE_SECTION_HEADER.Characteristics.off, sectFlags); + + // Extract alignment from Characteristics field + int alignshift = (sectFlags & IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_MASK) >> + IMAGE_SECTION_HEADER.IMAGE_SCN_ALIGN_SHIFT; + + // Use 8 byte alignment if not specified + if (alignshift == 0) + alignshift = 3; + else + --alignshift; + + align = 1 << alignshift; + + data = sectData; + hasrelocations = hasRelocations; + sectionIndex = sectIndex; + } + + public long getSize() { + return section.getInt(IMAGE_SECTION_HEADER.SizeOfRawData.off); + } + + public int getDataAlign() { + return (align); + } + + // Alignment requirements for the IMAGE_SECTION_HEADER structures + public static int getShdrAlign() { + return (4); + } + + public byte[] getArray() { + return section.array(); + } + + public byte[] getDataArray() { + return data; + } + + public void setOffset(long offset) { + section.putInt(IMAGE_SECTION_HEADER.PointerToRawData.off, (int)offset); + } + + public long getOffset() { + return (section.getInt(IMAGE_SECTION_HEADER.PointerToRawData.off)); + } + + public void setReloff(int offset) { + section.putInt(IMAGE_SECTION_HEADER.PointerToRelocations.off, offset); + } + + public void setRelcount(int count) { + // If the number of relocs is larger than 65K, then set + // the overflow bit. The real count will be written to + // the first reloc entry for this section. + if (count > 0xFFFF) { + int flags; + section.putChar(IMAGE_SECTION_HEADER.NumberOfRelocations.off, (char)0xFFFF); + flags = section.getInt(IMAGE_SECTION_HEADER.Characteristics.off); + flags |= IMAGE_SECTION_HEADER.IMAGE_SCN_LNK_NRELOC_OVFL; + section.putInt(IMAGE_SECTION_HEADER.Characteristics.off, flags); + } + else { + section.putChar(IMAGE_SECTION_HEADER.NumberOfRelocations.off, (char)count); + } + } + + public boolean hasRelocations() { + return hasrelocations; + } + + public int getSectionId() { + return sectionIndex; + } + +} + + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java new file mode 100644 index 00000000000..c305dbe071d --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymbol.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import jdk.tools.jaotc.binformat.NativeSymbol; +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffSymbol extends NativeSymbol { + ByteBuffer sym; + + public PECoffSymbol(int symbolindex, int strindex, byte type, byte storageclass, + byte sectindex, long offset, long size) { + super(symbolindex); + sym = PECoffByteBuffer.allocate(IMAGE_SYMBOL.totalsize); + + // We don't use short names + sym.putInt(IMAGE_SYMBOL.Short.off, 0); + + sym.putInt(IMAGE_SYMBOL.Long.off, strindex); + sym.putInt(IMAGE_SYMBOL.Value.off, (int)offset); + + // Section indexes start at 1 but we manage the index internally + // as 0 relative except in this structure + sym.putChar(IMAGE_SYMBOL.SectionNumber.off, (char)(sectindex+1)); + + sym.putChar(IMAGE_SYMBOL.Type.off, (char)type); + sym.put(IMAGE_SYMBOL.StorageClass.off, storageclass); + sym.put(IMAGE_SYMBOL.NumberOfAuxSymbols.off, (byte)0); + } + + public byte[] getArray() { + return sym.array(); + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java new file mode 100644 index 00000000000..34e0ef73f5e --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffSymtab.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; + +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL; +import jdk.tools.jaotc.binformat.pecoff.PECoffSymbol; +import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; + +public class PECoffSymtab { + ArrayListsymbols = new ArrayList(); + + /** + * number of symbols added + */ + int symbolCount; + + /** + * String holding symbol table strings + */ + private StringBuilder strTabContent; + + /** + * Keeps track of bytes in string table since strTabContent.length() + * is number of chars, not bytes. + */ + private int strTabNrOfBytes; + + /** + * String holding Linker Directives + */ + private StringBuilder directives; + + public PECoffSymtab() { + symbolCount = 0; + strTabContent = new StringBuilder(); + directives = new StringBuilder(); + + // The first 4 bytes of the string table contain + // the length of the table (including this length field). + strTabNrOfBytes = 4; + + // Make room for the 4 byte length field + strTabContent.append('\0').append('\0').append('\0').append('\0'); + + // Linker Directives start with 3 spaces to signify ANSI + directives.append(" "); + } + + public PECoffSymbol addSymbolEntry(String name, byte type, byte storageclass, + byte secHdrIndex, long offset, long size) { + // Get the current symbol index and append symbol name to string table. + int index; + PECoffSymbol sym; + + if (name.isEmpty()) { + index = 0; + strTabContent.append('\0'); + strTabNrOfBytes += 1; + sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset, size); + symbols.add(sym); + } else { + int nameSize = name.getBytes().length; + + // We can't trust strTabContent.length() since that is + // chars (UTF16), keep track of bytes on our own. + index = strTabNrOfBytes; + // strTabContent.append('_').append(name).append('\0'); + strTabContent.append(name).append('\0'); + strTabNrOfBytes += (nameSize + 1); + + sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset, size); + symbols.add(sym); + if (storageclass == IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL) + addDirective(name, type); + } + symbolCount++; + return (sym); + } + + private void addDirective(String name, byte type) { + directives.append("/EXPORT:" + name); + if(type != IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION) { + directives.append(",DATA"); + } + directives.append(" "); + } + + public int getSymtabCount() { + return symbolCount; + } + + public int getStrtabSize() { + return strTabNrOfBytes; + } + + // Return a byte array that contains the symbol table entries + public byte[] getSymtabArray() { + ByteBuffer symtabData = PECoffByteBuffer.allocate(symbolCount*IMAGE_SYMBOL.totalsize); + symtabData.order(ByteOrder.LITTLE_ENDIAN); + + // copy all symbols + for (int i = 0; i < symbolCount; i++ ) { + PECoffSymbol sym = symbols.get(i); + byte [] arr = sym.getArray(); + symtabData.put(arr); + } + return (symtabData.array()); + } + + // Return the string table array + public byte[] getStrtabArray() { + byte [] strs = strTabContent.toString().getBytes(); + + // Update the size of the string table + ByteBuffer buff = ByteBuffer.wrap(strs); + buff.order(ByteOrder.LITTLE_ENDIAN); + buff.putInt(0, strTabNrOfBytes); + + return (strs); + } + + public byte[] getDirectiveArray() { + return (directives.toString().getBytes()); + } +} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java new file mode 100644 index 00000000000..9c40f64733f --- /dev/null +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/pecoff/PECoffTargetInfo.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.tools.jaotc.binformat.pecoff; + +import java.nio.ByteOrder; +import jdk.tools.jaotc.binformat.pecoff.PECoff; +import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_FILE_HEADER; + +/** + * Class that abstracts MACH-O target details. + * + */ +public class PECoffTargetInfo { + /** + * Target architecture. + */ + private static final char arch; + + /** + * Target OS string. + */ + private static String osName; + + static { + // Find the target arch details + String archStr = System.getProperty("os.arch").toLowerCase(); + if (ByteOrder.nativeOrder() != ByteOrder.LITTLE_ENDIAN) { + System.out.println("Only Little Endian byte order supported!"); + } + + if (archStr.equals("amd64") || archStr.equals("x86_64")) { + arch = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_AMD64; + } else { + System.out.println("Unsupported architecture " + archStr); + arch = IMAGE_FILE_HEADER.IMAGE_FILE_MACHINE_UNKNOWN; + } + + osName = System.getProperty("os.name").toLowerCase(); + if (!osName.contains("windows")) { + System.out.println("Unsupported Operating System " + osName); + osName = "Unknown"; + } + } + + public static char getPECoffArch() { + return arch; + } + + public static String getOsName() { + return osName; + } +} + diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFSymbol.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFSymbol.java deleted file mode 100644 index ddad5a018da..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/ELFSymbol.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf; - -/** - * This class represents a {@code Elf32_Sym} or {@code Elf64_Sym} as defined in {@code elf.h}. - */ -public class ELFSymbol { - /** Symbol name. */ - private final String name; - - /** String table index. */ - private final int index; - - /** Native memory address of ELF sym entry. */ - private final Pointer address; - private final boolean isLocal; - - public ELFSymbol(String name, int index, Pointer address, boolean isLocal) { - this.name = name; - this.index = index; - this.address = address; - this.isLocal = isLocal; - } - - /** - * @return the name - */ - public String getName() { - return name; - } - - /** - * @return the index - */ - public int getIndex() { - return index; - } - - /** - * @return the address - */ - public Pointer getAddress() { - return address; - } - - @Override - public String toString() { - return "name=" + name + ", index=" + index + ", address=" + address; - } - - public boolean isLocal() { - return isLocal; - } -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFContainer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFContainer.java deleted file mode 100644 index 64d699f0371..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFContainer.java +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf; - -import static jdk.tools.jaotc.jnilibelf.UnsafeAccess.UNSAFE; - -import java.io.File; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF; -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.LibELF.Elf_Type; - -/** - * A class abstraction of an ELF file. - * - */ -public class JNIELFContainer { - - private String outputFileName; - private File outFile; - private int outFileDesc; - - /** - * Pointer to Elf file. This is the same as struct Elf found in libelf.h - */ - private Pointer elfPtr; - - /** - * Class of the ELF container - one of ELFCLASS32 or ELFCLASS64. - */ - private final int elfClass; - - /** - * Pointer to ELF Header. - */ - private Pointer ehdrPtr; - - /** - * Pointer to Program Header. - */ - private Pointer phdrPtr; - - /** - * String holding .shstrtab contents. - */ - private String shStrTabContent = ""; - - /** - * Map of local symbol indexes to ELF symbol entries. - */ - private List localSymbolIndex = new ArrayList<>(); - - /** - * Map of global symbol indexes to ELF symbol entries. - */ - private List globalSymbolIndex = new ArrayList<>(); - - /** - * String holding .strtab contents. - */ - private StringBuilder strTabContent = new StringBuilder(); - - /** - * Keeps track of nr of bytes in .strtab since strTabContent.length() is number of chars, not - * bytes. - */ - private int strTabNrOfBytes = 0; - - /** - * A hashtable that holds (section-name, relocation-table) pairs. For example, [(".rela.text", - * rela-text-reloc-entries), (".rela.plt", rela-plt-reloc-entries), ...]. - */ - private Map> relocTables = new HashMap<>(); - - /** - * Create reloca; 0 => false and non-zero => true. - */ - private final int createReloca; - - /** - * Construct an ELFContainer in preparation for a disk image with file {@code prefix}. - * - * @param fileName name of ELF file to be created - */ - public JNIELFContainer(String fileName, String aotVersion) { - // Check for version compatibility - if (!JNILibELFAPI.elfshim_version().equals(aotVersion)) { - throw new InternalError("libelfshim version mismatch: " + JNILibELFAPI.elfshim_version() + " vs " + aotVersion); - } - - elfClass = JNIELFTargetInfo.getELFClass(); - createReloca = JNIELFTargetInfo.createReloca(); - outputFileName = fileName; - } - - /** - * Get the local ELF symbol table. - * - * @return local symbol table - */ - public List getLocalSymbols() { - return localSymbolIndex; - } - - /** - * Get the global ELF symbol table. - * - * @return list of global ELF symbol table entries - */ - public List getGlobalSymbols() { - return globalSymbolIndex; - } - - /** - * Get string table content (.strtab). - * - * @return string table content - */ - public String getStrTabContent() { - return strTabContent.toString(); - } - - /** - * Get section header string table content (.shstrtab). - * - * @return section header string table content - */ - public String getShStrTabContent() { - return shStrTabContent; - } - - /** - * Get relocation tables. - * - * @return relocation tables - */ - public Map> getRelocTables() { - return relocTables; - } - - /** - * Get the index of first non-local symbol in symbol table. - * - * @return symbol table index - */ - public int getFirstNonLocalSymbolIndex() { - return localSymbolIndex.size(); - } - - /** - * Create ELF header of type {@code ececType}. - * - * @param type type of ELF executable - */ - public void createELFHeader(int type) { - // Check for version compatibility - if (JNILibELFAPI.elf_version(ELF.EV_CURRENT) == ELF.EV_NONE) { - throw new InternalError("ELF version mismatch"); - } - - outFile = constructRelocFile(outputFileName); - // Open a temporary file for the shared library to be created - // TODO: Revisit file permissions; need to add execute permission - outFileDesc = JNILibELFAPI.open_rw(outFile.getPath()); - - if (outFileDesc == -1) { - System.out.println("Failed to open file " + outFile.getPath() + " to write relocatable object."); - } - - elfPtr = JNILibELFAPI.elf_begin(outFileDesc, LibELF.Elf_Cmd.ELF_C_WRITE.intValue(), new Pointer(0L)); - if (elfPtr == null) { - throw new InternalError("elf_begin failed"); - } - - // Allocate new Ehdr of current architecture class - - ehdrPtr = JNILibELFAPI.gelf_newehdr(elfPtr, elfClass); - - JNILibELFAPI.ehdr_set_data_encoding(ehdrPtr, JNIELFTargetInfo.getELFEndian()); - JNILibELFAPI.set_Ehdr_e_machine(elfClass, ehdrPtr, JNIELFTargetInfo.getELFArch()); - JNILibELFAPI.set_Ehdr_e_type(elfClass, ehdrPtr, type); - JNILibELFAPI.set_Ehdr_e_version(elfClass, ehdrPtr, ELF.EV_CURRENT); - } - - /** - * If the file name has a .so extension, replace it with .o extension. Else just add .o - * extension - * - * @param fileName - * @return File object - */ - private static File constructRelocFile(String fileName) { - File relocFile = new File(fileName); - if (relocFile.exists()) { - if (!relocFile.delete()) { - throw new InternalError("Failed to delete existing " + fileName + " file"); - } - } - return relocFile; - } - - /** - * Create {@code count} number of Program headers. - * - * @param count number of program headers to create - * @return true upon success; false upon failure - */ - public boolean createProgramHeader(int count) { - phdrPtr = JNILibELFAPI.gelf_newphdr(elfPtr, count); - if (phdrPtr == null) { - System.out.println("gelf_newphdr error"); - return false; - } - return true; - } - - /** - * Set program header to be of type self. - * - * @return true - */ - public boolean setProgHdrTypeToSelf() { - // Set program header to be of type self - JNILibELFAPI.phdr_set_type_self(elfClass, ehdrPtr, phdrPtr); - // And thus mark it as dirty so that elfUpdate can recompute the structures - JNILibELFAPI.elf_flagphdr(elfPtr, LibELF.Elf_Cmd.ELF_C_SET.intValue(), LibELF.ELF_F_DIRTY); - // TODO: Error checking; look at the return value of elf_update - // and call elf_errmsg appropriately. - return true; - } - - /** - * Create a section. The corresponding section header and section data are created by calling - * the necessary libelf APIs. The section that is created is inserted into the ELF container. - * - * @param secName name of the section - * @param scnData section data - * @param dataType data type - * @param align section alignment - * @param scnType section type - * @param scnFlags section flags - * @param scnLink sh_link field of Elf{32,64}_Shdr - * @param scnInfo sh_info field of Elf{32,64}_Shdr - * @return section index - */ - public int createSection(String secName, byte[] scnData, Elf_Type dataType, int align, int scnType, int scnFlags, int scnLink, int scnInfo) { - // Create a new section - Pointer scnPtr = JNILibELFAPI.elf_newscn(elfPtr); - if (scnPtr == null) { - throw new InternalError("elf_newscn error"); - } - - // Allocate section data for the section - Pointer scnDataPtr = JNILibELFAPI.elf_newdata(scnPtr); - if (scnDataPtr == null) { - String errMsg = JNILibELFAPI.elf_errmsg(-1); - throw new InternalError("elf_newdata error: " + errMsg); - } - - // Get the pointer to section header associated with the new section - Pointer scnHdrPtr = JNILibELFAPI.elf64_getshdr(scnPtr); - - // Add name of the section to section name string - // If secName is null, point the name to the 0th index - // that holds `\0' - byte[] modScnData; - if (secName.isEmpty()) { - JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, 0); - modScnData = scnData; - } else { - if (secName.equals(".shstrtab")) { - // Modify .shstrtab data by inserting '\0' at index 0 - String shstrtabSecName = ".shstrtab" + '\0'; - // Additional byte for the '\0' at position 0 - ByteBuffer nbuf = ByteBuffer.allocate(scnData.length + 1 + shstrtabSecName.length()); - nbuf.put(0, (byte) 0); - nbuf.position(1); - nbuf.put(scnData); - nbuf.position(scnData.length + 1); - // Add the section name ".shstrtab" to its own data - nbuf.put(shstrtabSecName.getBytes(StandardCharsets.UTF_8)); - modScnData = nbuf.array(); - JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, scnData.length + 1); - // Set strtab section index - JNILibELFAPI.set_Ehdr_e_shstrndx(elfClass, ehdrPtr, JNILibELFAPI.elf_ndxscn(scnPtr)); - } else if (secName.equals(".strtab")) { - // Modify strtab section data to insert '\0' at position 0. - // Additional byte for the '\0' at position 0 - ByteBuffer nbuf = ByteBuffer.allocate(scnData.length + 1); - nbuf.put(0, (byte) 0); - nbuf.position(1); - nbuf.put(scnData); - modScnData = nbuf.array(); - // Set the sh_name - JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, shStrTabContent.length() + 1); - // Add scnName to stringList - shStrTabContent += secName + '\0'; - } else { - // Set the sh_name - JNILibELFAPI.set_Shdr_sh_name(elfClass, scnHdrPtr, shStrTabContent.length() + 1); - // Add scnName to stringList - shStrTabContent += secName + '\0'; - modScnData = scnData; - } - } - - final int scnDataBufSize = modScnData.length; - - Pointer scnDataBufPtr = null; - if (scnType != ELF.SHT_NOBITS) { - // Allocate native memory for section data - final long address = UNSAFE.allocateMemory(scnDataBufSize + 1); - scnDataBufPtr = new Pointer(address); - scnDataBufPtr.put(modScnData); - } else { - scnDataBufPtr = new Pointer(0L); - } - - // Set data descriptor fields - JNILibELFAPI.set_Data_d_align(scnDataPtr, align); - JNILibELFAPI.set_Data_d_buf(scnDataPtr, scnDataBufPtr); - JNILibELFAPI.set_Data_d_size(scnDataPtr, scnDataBufSize); - JNILibELFAPI.set_Data_d_off(scnDataPtr, 0); - JNILibELFAPI.set_Data_d_type(scnDataPtr, dataType.intValue()); - JNILibELFAPI.set_Data_d_version(scnDataPtr, ELF.EV_CURRENT); - - JNILibELFAPI.set_Shdr_sh_type(elfClass, scnHdrPtr, scnType); - JNILibELFAPI.set_Shdr_sh_flags(elfClass, scnHdrPtr, scnFlags); - JNILibELFAPI.set_Shdr_sh_entsize(elfClass, scnHdrPtr, 0); // TODO: Is this right?? - JNILibELFAPI.set_Shdr_sh_link(elfClass, scnHdrPtr, scnLink); - JNILibELFAPI.set_Shdr_sh_info(elfClass, scnHdrPtr, scnInfo); - - // Add hash section to section pointer list - int index = JNILibELFAPI.elf_ndxscn(scnPtr); - return index; - } - - /** - * Create an ELF symbol entry for a symbol with the given properties. - * - * @param name name of the section in which symName is referenced - * @param type type of symName - * @param bind binding of symName - * @param secHdrIndex section header index of the section in which symName is referenced - * (st_shndx of ELF symbol entry) - * @param size symName size (st_size of ELF symbol entry) - * @param value symName value (st_value of ELF symbol entry) - * @param isLocal true if symbol is local. - */ - public ELFSymbol createELFSymbolEntry(String name, int type, int bind, int secHdrIndex, int size, int value, boolean isLocal) { - // Get the current symbol index and append symbol name to string table. - int index; - if (name.isEmpty()) { - index = 0; - } else { - // NOTE: The +1 comes from the null symbol! - // We can't trust strTabContent.length() since that is chars (UTF16), keep track of - // bytes on our own. - index = strTabNrOfBytes + 1; - strTabContent.append(name).append('\0'); - strTabNrOfBytes += name.getBytes(StandardCharsets.UTF_8).length + 1; - } - - // Create ELF symbol entry - long address = JNILibELFAPI.create_sym_entry(elfClass, index, type, bind, secHdrIndex, size, value); - if (address == 0) { - throw new InternalError("create_sym_entry failed"); - } - Pointer ptr = new Pointer(address); - - if (isLocal) { - final int localIndex = localSymbolIndex.size(); - ELFSymbol symbol = new ELFSymbol(name, localIndex, ptr, isLocal); - localSymbolIndex.add(symbol); - return symbol; - } else { - final int globalIndex = globalSymbolIndex.size(); - ELFSymbol symbol = new ELFSymbol(name, globalIndex, ptr, isLocal); - globalSymbolIndex.add(symbol); - return symbol; - } - } - - /** - * Create an ELF relocation entry for given symbol {@code name} to section {@code secname}. - * - * @param container the section - * @param offset offset into the section contents at which the relocation needs to be applied - * @param type ELF type of the relocation entry - * @param addend Addend for for relocation of type reloca - */ - public void createELFRelocationEntry(ELFContainer container, int offset, int type, int addend, ELFSymbol elfSymbol) { - // Get the index of the symbol. - int index; - if (elfSymbol.isLocal()) { - index = elfSymbol.getIndex(); - } else { - /* - * For global symbol entries the index will be offset by the number of local symbols - * which will be listed first in the symbol table. - */ - index = elfSymbol.getIndex() + localSymbolIndex.size(); - } - - long address = JNILibELFAPI.create_reloc_entry(elfClass, offset, index, type, addend, createReloca); - if (address == 0) { - throw new InternalError("create_reloc_entry failed"); - } - Pointer ptr = new Pointer(address); - /* - * If section name associated with this symbol is set to undefined i.e., secname is null, - * symIndex is undef i.e., 0. - */ - if (relocTables.get(container) == null) { - // Allocate a new table and add it to the hash table of reloc tables - relocTables.put(container, new ArrayList<>()); - } - - // Add the entry - relocTables.get(container).add(ptr); - } - - /** - * Invokes native libelf function loff_t elf_update (Elf *elfPtr, Elf_Cmd cmd). - * - * @param cmd command - * @return return value of the native function called - */ - public boolean elfUpdate(LibELF.Elf_Cmd cmd) { - JNILibELFAPI.elf_update(elfPtr, cmd.intValue()); - // TODO: Error checking; look at the return value of elf_update - // and call elf_errmsg appropriately. - return true; - } - - /** - * Wrapper function that invokes int elf_end (Elf *elfPtr). and closes ELF output file - * descriptor - * - * @return true - */ - public boolean elfEnd() { - // Finish ELF processing - JNILibELFAPI.elf_end(elfPtr); - // Close file descriptor - JNILibELFAPI.close(outFileDesc); - return true; - } -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFRelocation.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFRelocation.java deleted file mode 100644 index 4c4cffd7abe..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFRelocation.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf; - -/** - * Class that abstracts ELF relocations. - * - */ -public interface JNIELFRelocation { - int R_UNDEF = -1; - - /** - * x86-specific relocation types. - * - */ - public interface I386 { - /* i386 relocs. */ - - int R_386_NONE = 0; /* No reloc */ - int R_386_32 = 1; /* Direct 32 bit */ - int R_386_PC32 = 2; /* PC relative 32 bit */ - int R_386_GOT32 = 3; /* 32 bit GOT entry */ - int R_386_PLT32 = 4; /* 32 bit PLT address */ - int R_386_COPY = 5; /* Copy symbol at runtime */ - int R_386_GLOB_DAT = 6; /* Create GOT entry */ - int R_386_JMP_SLOT = 7; /* Create PLT entry */ - int R_386_RELATIVE = 8; /* Adjust by program base */ - int R_386_GOTOFF = 9; /* 32 bit offset to GOT */ - int R_386_GOTPC = 10; /* 32 bit PC relative offset to GOT */ - int R_386_32PLT = 11; - int R_386_TLS_TPOFF = 14; /* Offset in static TLS block */ - int R_386_TLS_IE = 15; /* Address of GOT entry for static TLS block offset */ - int R_386_TLS_GOTIE = 16; /* GOT entry for static TLS block offset */ - int R_386_TLS_LE = 17; /* Offset relative to static TLS block */ - int R_386_TLS_GD = 18; /* Direct 32 bit for GNU version of general dynamic thread local data */ - int R_386_TLS_LDM = 19; /* - * Direct 32 bit for GNU version of local dynamic thread local data - * in LE code - */ - int R_386_16 = 20; - int R_386_PC16 = 21; - int R_386_8 = 22; - int R_386_PC8 = 23; - int R_386_TLS_GD_32 = 24; /* Direct 32 bit for general dynamic thread local data */ - int R_386_TLS_GD_PUSH = 25; /* Tag for pushl in GD TLS code */ - int R_386_TLS_GD_CALL = 26; /* Relocation for call to __tls_get_addr() */ - int R_386_TLS_GD_POP = 27; /* Tag for popl in GD TLS code */ - int R_386_TLS_LDM_32 = 28; /* Direct 32 bit for local dynamic thread local data in LE code */ - int R_386_TLS_LDM_PUSH = 29; /* Tag for pushl in LDM TLS code */ - int R_386_TLS_LDM_CALL = 30; /* Relocation for call to __tls_get_addr() in LDM code */ - int R_386_TLS_LDM_POP = 31; /* Tag for popl in LDM TLS code */ - int R_386_TLS_LDO_32 = 32; /* Offset relative to TLS block */ - int R_386_TLS_IE_32 = 33; /* GOT entry for negated static TLS block offset */ - int R_386_TLS_LE_32 = 34; /* Negated offset relative to static TLS block */ - int R_386_TLS_DTPMOD32 = 35; /* ID of module containing symbol */ - int R_386_TLS_DTPOFF32 = 36; /* Offset in TLS block */ - int R_386_TLS_TPOFF32 = 37; /* Negated offset in static TLS block */ - int R_386_SIZE32 = 38; /* 32-bit symbol size */ - int R_386_TLS_GOTDESC = 39; /* GOT offset for TLS descriptor. */ - int R_386_TLS_DESC_CALL = 40; /* Marker of call through TLS descriptor for relaxation. */ - int R_386_TLS_DESC = 41; /* - * TLS descriptor containing pointer to code and to argument, - * returning the TLS offset for the symbol. - */ - int R_386_IRELATIVE = 42; /* Adjust indirectly by program base */ - /* Keep this the last entry. */ - int R_386_NUM = 43; - } - - /** - * x86_64-specific relocation types. - */ - public interface X86_64 { - /* AMD x86-64 relocations. */ - int R_X86_64_NONE = 0; /* No reloc */ - int R_X86_64_64 = 1; /* Direct 64 bit */ - int R_X86_64_PC32 = 2; /* PC relative 32 bit signed */ - int R_X86_64_GOT32 = 3; /* 32 bit GOT entry */ - int R_X86_64_PLT32 = 4; /* 32 bit PLT address */ - int R_X86_64_COPY = 5; /* Copy symbol at runtime */ - int R_X86_64_GLOB_DAT = 6; /* Create GOT entry */ - int R_X86_64_JUMP_SLOT = 7; /* Create PLT entry */ - int R_X86_64_RELATIVE = 8; /* Adjust by program base */ - int R_X86_64_GOTPCREL = 9; /* 32 bit signed PC relative offset to GOT */ - int R_X86_64_32 = 10; /* Direct 32 bit zero extended */ - int R_X86_64_32S = 11; /* Direct 32 bit sign extended */ - int R_X86_64_16 = 12; /* Direct 16 bit zero extended */ - int R_X86_64_PC16 = 13; /* 16 bit sign extended pc relative */ - int R_X86_64_8 = 14; /* Direct 8 bit sign extended */ - int R_X86_64_PC8 = 15; /* 8 bit sign extended pc relative */ - int R_X86_64_DTPMOD64 = 16; /* ID of module containing symbol */ - int R_X86_64_DTPOFF64 = 17; /* Offset in module's TLS block */ - int R_X86_64_TPOFF64 = 18; /* Offset in initial TLS block */ - int R_X86_64_TLSGD = 19; /* - * 32 bit signed PC relative offset to two GOT entries for GD - * symbol - */ - int R_X86_64_TLSLD = 20; /* - * 32 bit signed PC relative offset to two GOT entries for LD - * symbol - */ - int R_X86_64_DTPOFF32 = 21; /* Offset in TLS block */ - int R_X86_64_GOTTPOFF = 22; /* - * 32 bit signed PC relative offset to GOT entry for IE symbol - */ - int R_X86_64_TPOFF32 = 23; /* Offset in initial TLS block */ - int R_X86_64_PC64 = 24; /* PC relative 64 bit */ - int R_X86_64_GOTOFF64 = 25; /* 64 bit offset to GOT */ - int R_X86_64_GOTPC32 = 26; /* 32 bit signed pc relative offset to GOT */ - int R_X86_64_GOT64 = 27; /* 64-bit GOT entry offset */ - int R_X86_64_GOTPCREL64 = 28; /* 64-bit PC relative offset to GOT entry */ - int R_X86_64_GOTPC64 = 29; /* 64-bit PC relative offset to GOT */ - int R_X86_64_GOTPLT64 = 30; /* like GOT64, says PLT entry needed */ - int R_X86_64_PLTOFF64 = 31; /* 64-bit GOT relative offset to PLT entry */ - int R_X86_64_SIZE32 = 32; /* Size of symbol plus 32-bit addend */ - int R_X86_64_SIZE64 = 33; /* Size of symbol plus 64-bit addend */ - int R_X86_64_GOTPC32_TLSDESC = 34; /* GOT offset for TLS descriptor. */ - int R_X86_64_TLSDESC_CALL = 35; /* - * Marker for call through TLS descriptor. - */ - int R_X86_64_TLSDESC = 36; /* TLS descriptor. */ - int R_X86_64_IRELATIVE = 37; /* Adjust indirectly by program base */ - int R_X86_64_RELATIVE64 = 38; /* 64-bit adjust by program base */ - - int R_X86_64_NUM = 39; - } -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFTargetInfo.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFTargetInfo.java deleted file mode 100644 index 8248d6fba29..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNIELFTargetInfo.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf; - -import java.nio.ByteOrder; - -import jdk.tools.jaotc.jnilibelf.JNILibELFAPI.ELF; - -/** - * Class that abstracts ELF target details. - * - */ -public class JNIELFTargetInfo { - /** - * ELF Class of the target. - */ - private static final int elfClass; - /** - * Target architecture. - */ - private static final int arch; - /** - * Architecture endian-ness. - */ - private static final int endian; - - /** - * Target OS string. - */ - private static final String osName; - - static { - // Find the target arch details - String archStr = System.getProperty("os.arch").toLowerCase(); - String datamodelStr = System.getProperty("sun.arch.data.model"); - - if (datamodelStr.equals("32")) { - elfClass = ELF.ELFCLASS32; - } else if (datamodelStr.equals("64")) { - elfClass = ELF.ELFCLASS64; - } else { - System.out.println("Failed to discover ELF class!"); - elfClass = ELF.ELFCLASSNONE; - } - - ByteOrder bo = ByteOrder.nativeOrder(); - if (bo == ByteOrder.LITTLE_ENDIAN) { - endian = ELF.ELFDATA2LSB; - } else if (bo == ByteOrder.BIG_ENDIAN) { - endian = ELF.ELFDATA2MSB; - } else { - System.out.println("Failed to discover endian-ness!"); - endian = ELF.ELFDATANONE; - } - - if (archStr.equals("x86")) { - arch = ELF.EM_386; - } else if (archStr.equals("amd64") || archStr.equals("x86_64")) { - arch = ELF.EM_X64_64; - } else if (archStr.equals("sparcv9")) { - arch = ELF.EM_SPARCV9; - } else { - System.out.println("Unsupported architecture " + archStr); - arch = ELF.EM_NONE; - } - - osName = System.getProperty("os.name").toLowerCase(); - } - - public static int getELFArch() { - return arch; - } - - public static int getELFClass() { - return elfClass; - } - - public static int getELFEndian() { - return endian; - } - - public static String getOsName() { - return osName; - } - - public static int createReloca() { - switch (arch) { - case ELF.EM_X64_64: - return 1; - default: - return 0; - } - } - - public static int sizeOfSymtabEntry() { - return JNILibELFAPI.size_of_Sym(elfClass); - } - - public static int sizeOfRelocEntry() { - if (createReloca() == 1) { - return JNILibELFAPI.size_of_Rela(elfClass); - } else { - return JNILibELFAPI.size_of_Rel(elfClass); - } - } -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNILibELFAPI.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNILibELFAPI.java deleted file mode 100644 index 5dc277b16ed..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/JNILibELFAPI.java +++ /dev/null @@ -1,677 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf; - -public class JNILibELFAPI { - - static { - System.loadLibrary("jelfshim"); - } - - /** - * Definitions for file open. - */ - public static enum OpenFlags { - O_RDONLY(0x0), - O_WRONLY(0x1), - O_RDWR(0x2), - O_CREAT(0x40); - - private final int intVal; - - private OpenFlags(int v) { - intVal = v; - } - - public int intValue() { - return intVal; - } - } - - /** - * Definitions reflecting those in elf.h. - * - */ - public interface ELF { - int EI_NIDENT = 16; - - int EI_CLASS = 4; /* File class byte index */ - int ELFCLASSNONE = 0; /* Invalid class */ - int ELFCLASS32 = 1; /* 32-bit objects */ - int ELFCLASS64 = 2; /* 64-bit objects */ - int ELFCLASSNUM = 3; - - int EI_DATA = 5; /* Data encoding byte index */ - int ELFDATANONE = 0; /* Invalid data encoding */ - int ELFDATA2LSB = 1; /* 2's complement, little endian */ - int ELFDATA2MSB = 2; /* 2's complement, big endian */ - int ELFDATANUM = 3; - - // Legal architecture values for e_machine (add others as needed) - int EM_NONE = 0; /* No machine */ - int EM_SPARC = 2; /* SUN SPARC */ - int EM_386 = 3; /* Intel 80386 */ - int EM_SPARCV9 = 43; /* SPARC v9 64-bit */ - int EM_X64_64 = 62; /* AMD x86-64 architecture */ - - /* Legal values for e_type (object file type). */ - - int ET_NONE = 0; /* No file type */ - int ET_REL = 1; /* Relocatable file */ - int ET_EXEC = 2; /* Executable file */ - int ET_DYN = 3; /* Shared object file */ - int ET_CORE = 4; /* Core file */ - int ET_NUM = 5; /* Number of defined types */ - int ET_LOOS = 0xfe00; /* OS-specific range start */ - int ET_HIOS = 0xfeff; /* OS-specific range end */ - int ET_LOPROC = 0xff00; /* Processor-specific range start */ - int ET_HIPROC = 0xffff; /* Processor-specific range end */ - - /* Legal values for e_version (version). */ - - int EV_NONE = 0; /* Invalid ELF version */ - int EV_CURRENT = 1; /* Current version */ - int EV_NUM = 2; - - /* Legal values for p_type (segment type). */ - - int PT_NULL = 0; /* Program header table entry unused */ - int PT_LOAD = 1; /* Loadable program segment */ - int PT_DYNAMIC = 2; /* Dynamic linking information */ - int PT_INTERP = 3; /* Program interpreter */ - int PT_NOTE = 4; /* Auxiliary information */ - int PT_SHLIB = 5; /* Reserved */ - int PT_PHDR = 6; /* Entry for header table itself */ - int PT_TLS = 7; /* Thread-local storage segment */ - int PT_NUM = 8; /* Number of defined types */ - int PT_LOOS = 0x60000000; /* Start of OS-specific */ - int PT_GNU_EH_FRAME = 0x6474e550; /* GCC .eh_frame_hdr segment */ - int PT_GNU_STACK = 0x6474e551; /* Indicates stack executability */ - int PT_GNU_RELRO = 0x6474e552; /* Read-only after relocation */ - int PT_LOSUNW = 0x6ffffffa; - int PT_SUNWBSS = 0x6ffffffa; /* Sun Specific segment */ - int PT_SUNWSTACK = 0x6ffffffb; /* Stack segment */ - int PT_HISUNW = 0x6fffffff; - int PT_HIOS = 0x6fffffff; /* End of OS-specific */ - int PT_LOPROC = 0x70000000; /* Start of processor-specific */ - int PT_HIPROC = 0x7fffffff; /* End of processor-specific */ - - /* Special section indices. */ - - int SHN_UNDEF = 0; /* Undefined section */ - int SHN_LORESERVE = 0xff00; /* Start of reserved indices */ - int SHN_LOPROC = 0xff00; /* Start of processor-specific */ - int SHN_BEFORE = 0xff00; /* Order section before all others (Solaris). */ - int SHN_AFTER = 0xff01; /* Order section after all others (Solaris). */ - int SHN_HIPROC = 0xff1f; /* End of processor-specific */ - int SHN_LOOS = 0xff20; /* Start of OS-specific */ - int SHN_HIOS = 0xff3f; /* End of OS-specific */ - int SHN_ABS = 0xfff1; /* Associated symbol is absolute */ - int SHN_COMMON = 0xfff2; /* Associated symbol is common */ - int SHN_XINDEX = 0xffff; /* Index is in extra table. */ - int SHN_HIRESERVE = 0xffff; /* End of reserved indices */ - - /* Legal values for sh_type (section type). */ - - int SHT_NULL = 0; /* Section header table entry unused */ - int SHT_PROGBITS = 1; /* Program data */ - int SHT_SYMTAB = 2; /* Symbol table */ - int SHT_STRTAB = 3; /* String table */ - int SHT_RELA = 4; /* Relocation entries with addends */ - int SHT_HASH = 5; /* Symbol hash table */ - int SHT_DYNAMIC = 6; /* Dynamic linking information */ - int SHT_NOTE = 7; /* Notes */ - int SHT_NOBITS = 8; /* Program space with no data (bss) */ - int SHT_REL = 9; /* Relocation entries, no addends */ - int SHT_SHLIB = 10; /* Reserved */ - int SHT_DYNSYM = 11; /* Dynamic linker symbol table */ - int SHT_INIT_ARRAY = 14; /* Array of constructors */ - int SHT_FINI_ARRAY = 15; /* Array of destructors */ - int SHT_PREINIT_ARRAY = 16; /* Array of pre-constructors */ - int SHT_GROUP = 17; /* Section group */ - int SHT_SYMTAB_SHNDX = 18; /* Extended section indeces */ - int SHT_NUM = 19; /* Number of defined types. */ - int SHT_LOOS = 0x60000000; /* Start OS-specific. */ - int SHT_GNU_ATTRIBUTES = 0x6ffffff5; /* Object attributes. */ - int SHT_GNU_HASH = 0x6ffffff6; /* GNU-style hash table. */ - int SHT_GNU_LIBLIST = 0x6ffffff7; /* Prelink library list */ - int SHT_CHECKSUM = 0x6ffffff8; /* Checksum for DSO content. */ - int SHT_LOSUNW = 0x6ffffffa; /* Sun-specific low bound. */ - int SHT_SUNW_move = 0x6ffffffa; - int SHT_SUNW_COMDAT = 0x6ffffffb; - int SHT_SUNW_syminfo = 0x6ffffffc; - int SHT_GNU_verdef = 0x6ffffffd; /* Version definition section. */ - int SHT_GNU_verneed = 0x6ffffffe; /* Version needs section. */ - int SHT_GNU_versym = 0x6fffffff; /* Version symbol table. */ - int SHT_HISUNW = 0x6fffffff; /* Sun-specific high bound. */ - int SHT_HIOS = 0x6fffffff; /* End OS-specific type */ - int SHT_LOPROC = 0x70000000; /* Start of processor-specific */ - int SHT_HIPROC = 0x7fffffff; /* End of processor-specific */ - int SHT_LOUSER = 0x80000000; /* Start of application-specific */ - int SHT_HIUSER = 0x8fffffff; /* End of application-specific */ - - /* Legal values for sh_flags (section flags). */ - - int SHF_WRITE = (1 << 0); /* Writable */ - int SHF_ALLOC = (1 << 1); /* Occupies memory during execution */ - int SHF_EXECINSTR = (1 << 2); /* Executable */ - int SHF_MERGE = (1 << 4); /* Might be merged */ - int SHF_STRINGS = (1 << 5); /* Contains nul-terminated strings */ - int SHF_INFO_LINK = (1 << 6); /* `sh_info' contains SHT index */ - int SHF_LINK_ORDER = (1 << 7); /* Preserve order after combining */ - int SHF_OS_NONCONFORMING = (1 << 8); /* Non-standard OS specific handling required */ - int SHF_GROUP = (1 << 9); /* Section is member of a group. */ - int SHF_TLS = (1 << 10); /* Section hold thread-local data. */ - int SHF_MASKOS = 0x0ff00000; /* OS-specific. */ - int SHF_MASKPROC = 0xf0000000; /* Processor-specific */ - int SHF_ORDERED = (1 << 30); /* Special ordering requirement (Solaris). */ - int SHF_EXCLUDE = (1 << 31); /* - * Section is excluded unless referenced or allocated - * (Solaris). - */ - - /* Legal values for ST_BIND subfield of st_info (symbol binding). */ - - int STB_LOCAL = 0; /* Local symbol */ - int STB_GLOBAL = 1; /* Global symbol */ - int STB_WEAK = 2; /* Weak symbol */ - int STB_NUM = 3; /* Number of defined types. */ - int STB_LOOS = 10; /* Start of OS-specific */ - int STB_GNU_UNIQUE = 10; /* Unique symbol. */ - int STB_HIOS = 12; /* End of OS-specific */ - int STB_LOPROC = 13; /* Start of processor-specific */ - int STB_HIPROC = 15; /* End of processor-specific */ - - /* Legal values for ST_TYPE subfield of st_info (symbol type). */ - - int STT_NOTYPE = 0; /* Symbol type is unspecified */ - int STT_OBJECT = 1; /* Symbol is a data object */ - int STT_FUNC = 2; /* Symbol is a code object */ - int STT_SECTION = 3; /* Symbol associated with a section */ - int STT_FILE = 4; /* Symbol's name is file name */ - int STT_COMMON = 5; /* Symbol is a common data object */ - int STT_TLS = 6; /* Symbol is thread-local data object */ - int STT_NUM = 7; /* Number of defined types. */ - int STT_LOOS = 10; /* Start of OS-specific */ - int STT_GNU_IFUNC = 10; /* Symbol is indirect code object */ - int STT_HIOS = 12; /* End of OS-specific */ - int STT_LOPROC = 13; /* Start of processor-specific */ - int STT_HIPROC = 15; /* End of processor-specific */ - } - - /** - * Definitions reflecting those in libelf.h. - * - */ - public interface LibELF { - - public static enum Elf_Cmd { - ELF_C_NULL("NULL"), /* Nothing, terminate, or compute only. */ - ELF_C_READ("READ"), /* Read .. */ - ELF_C_RDWR("RDWR"), /* Read and write .. */ - ELF_C_WRITE("WRITE"), /* Write .. */ - ELF_C_CLR("CLR"), /* Clear flag. */ - ELF_C_SET("SET"), /* Set flag. */ - ELF_C_FDDONE("FDDONE"), /* - * Signal that file descriptor will not be used anymore. - */ - ELF_C_FDREAD("FDREAD"), /* - * Read rest of data so that file descriptor is not used - * anymore. - */ - /* The following are Linux-only extensions. */ - ELF_C_READ_MMAP("READ_MMAP"), /* Read, but mmap the file if possible. */ - ELF_C_RDWR_MMAP("RDWR_MMAP"), /* Read and write, with mmap. */ - ELF_C_WRITE_MMAP("WRITE_MMAP"), /* Write, with mmap. */ - ELF_C_READ_MMAP_PRIVATE("READ_MMAP_PRIVATE"), /* - * Read, but memory is writable, results - * are not written to the file. - */ - ELF_C_EMPTY("EMPTY"), /* Copy basic file data but not the content. */ - /* The following are SunOS-only enums */ - ELF_C_WRIMAGE("WRIMAGE"), - ELF_C_IMAGE("IMAGE"), - /* Common last entry. */ - ELF_C_NUM("NUM"); - private final int intVal; - private final String name; - - private Elf_Cmd(String cmd) { - name = "ELF_C_" + cmd; - switch (cmd) { - case "NULL": - // ELF_C_NULL has the same enum ordinal on both Linux and SunOS - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_NULL.ordinal(); - break; - - case "READ": - // ELF_C_READ has the same enum ordinal on both Linux and SunOS - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ.ordinal(); - break; - - // Enums defined in libelf.h of both Linux and SunOS - // but with different ordinals - case "RDWR": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_RDWR.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_RDWR.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "WRITE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_WRITE.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_WRITE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "CLR": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_CLR.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_CLR.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "SET": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_SET.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_SET.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "FDDONE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_FDDONE.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_FDDONE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "FDREAD": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_FDREAD.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_FDREAD.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "NUM": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_NUM.ordinal(); - } else if (JNIELFTargetInfo.getOsName().equals("sunos")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_NUM.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - // Linux-only Elf_Cmd enums - case "READ_MMAP": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ_MMAP.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "RDWR_MMAP": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_RDWR_MMAP.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "WRITE_MMAP": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_WRITE_MMAP.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "READ_MMAP_PRIVATE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_READ_MMAP_PRIVATE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - - case "EMPTY": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.linux.Elf_Cmd.ELF_C_EMPTY.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - // SunOS-only Elf_Cmd enums - case "WRIMAGE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_WRIMAGE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - case "IMAGE": - if (JNIELFTargetInfo.getOsName().equals("linux")) { - intVal = jdk.tools.jaotc.jnilibelf.sunos.Elf_Cmd.ELF_C_IMAGE.ordinal(); - } else { - // Unsupported platform - intVal = -1; - } - break; - default: - intVal = -1; - } - } - - public int intValue() { - assert intVal != -1 : "enum " + name + "not supported on " + JNIELFTargetInfo.getOsName(); - return intVal; - } - - public String getName() { - return name; - } - } - - public static enum Elf_Type { - ELF_T_BYTE(0), /* unsigned char */ - ELF_T_ADDR(1), /* Elf32_Addr, Elf64_Addr, ... */ - ELF_T_DYN(2), /* Dynamic section record. */ - ELF_T_EHDR(3), /* ELF header. */ - ELF_T_HALF(4), /* Elf32_Half, Elf64_Half, ... */ - ELF_T_OFF(5), /* Elf32_Off, Elf64_Off, ... */ - ELF_T_PHDR(6), /* Program header. */ - ELF_T_RELA(7), /* Relocation entry with addend. */ - ELF_T_REL(8), /* Relocation entry. */ - ELF_T_SHDR(9), /* Section header. */ - ELF_T_SWORD(10), /* Elf32_Sword, Elf64_Sword, ... */ - ELF_T_SYM(11), /* Symbol record. */ - ELF_T_WORD(12), /* Elf32_Word, Elf64_Word, ... */ - ELF_T_XWORD(13), /* Elf32_Xword, Elf64_Xword, ... */ - ELF_T_SXWORD(14), /* Elf32_Sxword, Elf64_Sxword, ... */ - ELF_T_VDEF(15), /* Elf32_Verdef, Elf64_Verdef, ... */ - ELF_T_VDAUX(16), /* Elf32_Verdaux, Elf64_Verdaux, ... */ - ELF_T_VNEED(17), /* Elf32_Verneed, Elf64_Verneed, ... */ - ELF_T_VNAUX(18), /* Elf32_Vernaux, Elf64_Vernaux, ... */ - ELF_T_NHDR(19), /* Elf32_Nhdr, Elf64_Nhdr, ... */ - ELF_T_SYMINFO(20), /* Elf32_Syminfo, Elf64_Syminfo, ... */ - ELF_T_MOVE(21), /* Elf32_Move, Elf64_Move, ... */ - ELF_T_LIB(22), /* Elf32_Lib, Elf64_Lib, ... */ - ELF_T_GNUHASH(23), /* GNU-style hash section. */ - ELF_T_AUXV(24), /* Elf32_auxv_t, Elf64_auxv_t, ... */ - /* Keep this the last entry. */ - ELF_T_NUM(25); - - private final int intVal; - - private Elf_Type(int v) { - intVal = v; - } - - public int intValue() { - return intVal; - } - } - - /* Flags for the ELF structures. */ - int ELF_F_DIRTY = 0x1; - int ELF_F_LAYOUT = 0x4; - int ELF_F_PERMISSIVE = 0x8; - - public static enum Elf_Kind { - ELF_K_NONE(0), /* Unknown. */ - ELF_K_AR(1), /* Archive. */ - ELF_K_COFF(2), /* Stupid old COFF. */ - ELF_K_ELF(3), /* ELF file. */ - /* Keep this the last entry. */ - ELF_K_NUM(4); - private final int intVal; - - private Elf_Kind(int v) { - intVal = v; - } - - public int intValue() { - return intVal; - } - } - } - - /** - * Invoke native libelf function unsigned int elf_version (unsigned int v). - * - * @param v version - * @return return value of native call - */ - // Checkstyle: stop method name check - static native int elf_version(int v); - - /** - * Return version recorded in libelfshim. - * - * @return return version string - */ - // Checkstyle: stop method name check - static native String elfshim_version(); - - /** - * Invoke native libelf function Elf *elf_begin (int fildes, Elf_Cmd cmd, Elf *elfPtr). - * - * @param fildes open file descriptor - * @param elfCRead command - * @param elfHdrPtr pointer to ELF header - * @return return value of native call - */ - static native Pointer elf_begin(int fildes, int elfCRead, Pointer elfHdrPtr); - - /** - * Invoke native libelf function elf_end (Elf *elfPtr). - * - * @param elfPtr pointer to ELF header - * @return return value of native call - */ - static native int elf_end(Pointer elfPtr); - - /** - * Invoke native libelf function elf_end (Elf *elfPtr). - * - * @param elfPtr pointer to ELF header - * @return return value of native call - */ - static native int elf_kind(Pointer elfPtr); - - /** - * Invoke native libelf function unsigned int elf_flagphdr (Elf *elf, Elf_Cmd cmd, unsigned int - * flags). - * - * @param elfPtr Pointer to ELF descriptor - * @param cmd command - * @param flags flags - * @return return value of native call - */ - static native int elf_flagphdr(Pointer elfPtr, int cmd, int flags); - - /** - * Invoke native libelf function Elf_Scn *elf_newscn (Elf *elfPtr). - * - * @param elfPtr Elf header pointer - * @return return value of native call - */ - static native Pointer elf_newscn(Pointer elfPtr); - - /** - * Invoke native libelf function Elf_Data *elf_newdata (Elf_Scn *scn). - * - * @param scnPtr pointer to section for which the new data descriptor is to be created - * @return return value of native call - */ - static native Pointer elf_newdata(Pointer scnPtr); - - /** - * Invoke native libelf function Elf64_Shdr *elf64_getshdr (Elf_Scn *scnPtr). - * - * @param scnPtr pointer to section whose header information is to be retrieved - * @return return value of native call - */ - static native Pointer elf64_getshdr(Pointer scnPtr); - - /** - * Invoke native libelf function loff_t elf_update (Elf *elfPtr, Elf_Cmd cmd). - * - * @param elfPtr Pointer to ELF descriptor - * @param cmd command - * @return return value of native call - */ - static native long elf_update(Pointer elfPtr, int cmd); - - /** - * Invoke native libelf function char *elf_errmsg (int error). - * - * @param error error - * @return return value of native call - */ - static native String elf_errmsg(int error); - - /** - * Invoke native libelf function size_t elf_ndxscn (Elf_Scn *scn). - * - * @param scn section pointer - * @return return value of native call - */ - static native int elf_ndxscn(Pointer scn); - - /** - * GELF interfaces - */ - /** - * Invoke native libelf function unsigned long int gelf_newehdr (Elf *elf, int elfClass). - * - * @param elf ELF Header pointer - * @param elfclass ELF class - * @return return value of native call boxed as a pointer - */ - static native Pointer gelf_newehdr(Pointer elf, int elfclass); - - /** - * Invoke native libelf function unsigned long int gelf_newphdr (Elf *elf, size_t phnum). - * - * @param elf ELF header pointer - * @param phnum number of program headers - * @return return value of native call boxed as a pointer - */ - static native Pointer gelf_newphdr(Pointer elf, int phnum); - - /** - * Miscellaneous convenience native methods that help peek and poke ELF data structures. - */ - static native int size_of_Sym(int elfClass); - - static native int size_of_Rela(int elfClass); - - static native int size_of_Rel(int elfClass); - - static native void ehdr_set_data_encoding(Pointer ehdr, int val); - - static native void set_Ehdr_e_machine(int elfclass, Pointer structPtr, int val); - - static native void set_Ehdr_e_type(int elfclass, Pointer structPtr, int val); - - static native void set_Ehdr_e_version(int elfclass, Pointer structPtr, int val); - - static native void set_Ehdr_e_shstrndx(int elfclass, Pointer structPtr, int val); - - static native void phdr_set_type_self(int elfclass, Pointer ehdr, Pointer phdr); - - static native void set_Shdr_sh_name(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_type(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_flags(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_entsize(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_link(int elfclass, Pointer structPtr, int val); - - static native void set_Shdr_sh_info(int elfclass, Pointer structPtr, int val); - - static native void set_Data_d_align(Pointer structPtr, int val); - - static native void set_Data_d_off(Pointer structPtr, int val); - - static native void set_Data_d_buf(Pointer structPtr, Pointer val); - - static native void set_Data_d_type(Pointer structPtr, int val); - - static native void set_Data_d_size(Pointer structPtr, int val); - - static native void set_Data_d_version(Pointer structPtr, int val); - - static native long create_sym_entry(int elfclass, int index, int type, int bind, int shndx, int size, int value); - - static native long create_reloc_entry(int elfclass, int roffset, int symtabIdx, int relocType, int raddend, int reloca); - - /** - * File Operations. - */ - static native int open_rw(String fileName); - - static native int open(String fileName, int flags); - - static native int open(String fileName, int flags, int mode); - - static native int close(int fd); - // Checkstyle: resume method name check -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/Pointer.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/Pointer.java deleted file mode 100644 index a569584a8ce..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/Pointer.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf; - -import jdk.internal.misc.Unsafe; - -import static jdk.tools.jaotc.jnilibelf.UnsafeAccess.UNSAFE; - -public class Pointer { - - private final long address; - - public Pointer(long val) { - address = val; - } - - /** - * Put (i.e., copy) content of byte array at consecutive addresses beginning at this Pointer. - * - * @param src source byte array - */ - public void put(byte[] src) { - UNSAFE.copyMemory(src, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, address, src.length); - } - - /** - * Get (i.e., copy) content at this Pointer to the given byte array. - * - * @param dst destination byte array - */ - public void get(byte[] dst) { - UNSAFE.copyMemory(null, address, dst, Unsafe.ARRAY_BYTE_BASE_OFFSET, dst.length); - } - - /** - * Read {@code readSize} number of bytes to copy them starting at {@code startIndex} of - * {@code byteArray} - * - * @param byteArray target array to copy bytes - * @param readSize number of bytes to copy - * @param startIndex index of the array to start copy at - */ - public void copyBytesTo(byte[] byteArray, int readSize, int startIndex) { - long end = (long)startIndex + (long)readSize; - if (end > byteArray.length) { - throw new IllegalArgumentException("writing beyond array bounds"); - } - UNSAFE.copyMemory(null, address, byteArray, Unsafe.ARRAY_BYTE_BASE_OFFSET+startIndex, readSize); - } - -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/linux/Elf_Cmd.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/linux/Elf_Cmd.java deleted file mode 100644 index a32d202486c..00000000000 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.jnilibelf/src/jdk/tools/jaotc/jnilibelf/linux/Elf_Cmd.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.tools.jaotc.jnilibelf.linux; - -/** - * Represent Elf_Cmd enums defined in libelf.h on Linux as they slightly different from libelf.h on - * SunOS. - */ -public enum Elf_Cmd { - /** Nothing, terminate, or compute only. */ - ELF_C_NULL, - - /** Read. */ - ELF_C_READ, - - /** Read and write. */ - ELF_C_RDWR, - - /** Write. */ - ELF_C_WRITE, - - /** Clear flag. */ - ELF_C_CLR, - - /** Set flag. */ - ELF_C_SET, - - /** - * Signal that file descriptor will not be used anymore. - */ - ELF_C_FDDONE, - - /** - * Read rest of data so that file descriptor is not used anymore. - */ - ELF_C_FDREAD, - - /* The following are extensions. */ - - /** Read, but mmap the file if possible. */ - ELF_C_READ_MMAP, - - /** Read and write, with mmap. */ - ELF_C_RDWR_MMAP, - - /** Write, with mmap. */ - ELF_C_WRITE_MMAP, - - /** - * Read, but memory is writable, results are not written to the file. - */ - ELF_C_READ_MMAP_PRIVATE, - - /** Copy basic file data but not the content. */ - ELF_C_EMPTY, - - /** Keep this the last entry. */ - ELF_C_NUM; -} diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java index 3ba1067b959..9f71f1cad7e 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java @@ -23,17 +23,11 @@ package jdk.tools.jaotc; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; - import java.util.ListIterator; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.GraalCompiler; -import org.graalvm.compiler.core.common.CompilationIdentifier; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -43,8 +37,7 @@ import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; @@ -60,19 +53,18 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.TriState; public class AOTBackend { - private final Main main; - + private final OptionValues graalOptions; private final HotSpotBackend backend; - private final HotSpotProviders providers; private final HotSpotCodeCacheProvider codeCache; private final PhaseSuite graphBuilderSuite; private final HighTierContext highTierContext; private final GraalFilters filters; - public AOTBackend(Main main, HotSpotBackend backend, GraalFilters filters) { + public AOTBackend(Main main, OptionValues graalOptions, HotSpotBackend backend, GraalFilters filters) { this.main = main; + this.graalOptions = graalOptions; this.backend = backend; this.filters = filters; providers = backend.getProviders(); @@ -85,37 +77,44 @@ public class AOTBackend { return graphBuilderSuite; } + public HotSpotBackend getBackend() { + return backend; + } + + public HotSpotProviders getProviders() { + return providers; + } + private Suites getSuites() { // create suites every time, as we modify options for the compiler - return backend.getSuites().getDefaultSuites(); + return backend.getSuites().getDefaultSuites(graalOptions); } private LIRSuites getLirSuites() { // create suites every time, as we modify options for the compiler - return backend.getSuites().getDefaultLIRSuites(); + return backend.getSuites().getDefaultLIRSuites(graalOptions); } @SuppressWarnings("try") - public CompilationResult compileMethod(ResolvedJavaMethod resolvedMethod) { - try (OverrideScope s = OptionValue.override(ImmutableCode, true, GeneratePIC, true)) { - StructuredGraph graph = buildStructuredGraph(resolvedMethod); - if (graph != null) { - return compileGraph(resolvedMethod, graph); - } - return null; + public CompilationResult compileMethod(ResolvedJavaMethod resolvedMethod, DebugContext debug) { + StructuredGraph graph = buildStructuredGraph(resolvedMethod, debug); + if (graph != null) { + return compileGraph(resolvedMethod, graph, debug); } + return null; } /** * Build a structured graph for the member. * * @param javaMethod method for whose code the graph is to be created + * @param debug * @return structured graph */ @SuppressWarnings("try") - private StructuredGraph buildStructuredGraph(ResolvedJavaMethod javaMethod) { - try (Scope s = Debug.scope("AOTParseMethod")) { - StructuredGraph graph = new StructuredGraph(javaMethod, StructuredGraph.AllowAssumptions.NO, false, CompilationIdentifier.INVALID_COMPILATION_ID); + private StructuredGraph buildStructuredGraph(ResolvedJavaMethod javaMethod, DebugContext debug) { + try (DebugContext.Scope s = debug.scope("AOTParseMethod")) { + StructuredGraph graph = new StructuredGraph.Builder(graalOptions, debug).method(javaMethod).useProfilingInfo(false).build(); graphBuilderSuite.apply(graph, highTierContext); return graph; } catch (Throwable e) { @@ -125,8 +124,8 @@ public class AOTBackend { } @SuppressWarnings("try") - private CompilationResult compileGraph(ResolvedJavaMethod resolvedMethod, StructuredGraph graph) { - try (Scope s = Debug.scope("AOTCompileMethod")) { + private CompilationResult compileGraph(ResolvedJavaMethod resolvedMethod, StructuredGraph graph, DebugContext debug) { + try (DebugContext.Scope s = debug.scope("AOTCompileMethod")) { ProfilingInfo profilingInfo = DefaultProfilingInfo.get(TriState.FALSE); final boolean isImmutablePIC = true; @@ -195,7 +194,7 @@ public class AOTBackend { public void printCompiledMethod(HotSpotResolvedJavaMethod resolvedMethod, CompilationResult compResult) { // This is really not installing the method. - InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(null, null, compResult), null, null); + InstalledCode installedCode = codeCache.addCode(resolvedMethod, HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult), null, null); String disassembly = codeCache.disassemble(installedCode); if (disassembly != null) { main.printlnDebug(disassembly); diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java index f92ead4ba25..9a1aef5c2b5 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -26,13 +26,15 @@ package jdk.tools.jaotc; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.GraalCompilerOptions; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugEnvironment; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Management; import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.DebugScope; +import org.graalvm.compiler.debug.DebugContext.Activation; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; @@ -54,6 +56,8 @@ public class AOTCompilationTask implements Runnable, Comparable { private final Main main; + private OptionValues graalOptions; + /** * The compilation id of this task. */ @@ -73,9 +77,10 @@ public class AOTCompilationTask implements Runnable, Comparable { */ private CompiledMethodInfo result; - public AOTCompilationTask(Main main, AOTCompiledClass holder, ResolvedJavaMethod method, AOTBackend aotBackend) { + public AOTCompilationTask(Main main, OptionValues graalOptions, AOTCompiledClass holder, ResolvedJavaMethod method, AOTBackend aotBackend) { this.main = main; - this.id = ids.getAndIncrement(); + this.graalOptions = graalOptions; + this.id = ids.incrementAndGet(); this.holder = holder; this.method = method; this.aotBackend = aotBackend; @@ -84,50 +89,46 @@ public class AOTCompilationTask implements Runnable, Comparable { /** * Compile a method or a constructor. */ + @SuppressWarnings("try") public void run() { // Ensure a JVMCI runtime is initialized prior to Debug being initialized as the former // may include processing command line options used by the latter. HotSpotJVMCIRuntime.runtime(); - // Ensure a debug configuration for this thread is initialized - if (Debug.isEnabled() && DebugScope.getConfig() == null) { - DebugEnvironment.initialize(TTY.out); - } AOTCompiler.logCompilation(MiscUtils.uniqueMethodName(method), "Compiling"); final long threadId = Thread.currentThread().getId(); - final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue() && !TTY.isSuppressed(); - final boolean printAfterCompilation = GraalCompilerOptions.PrintAfterCompilation.getValue() && !TTY.isSuppressed(); + final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue(graalOptions) && !TTY.isSuppressed(); if (printCompilation) { TTY.println(getMethodDescription() + "..."); } final long start; final long allocatedBytesBefore; - if (printAfterCompilation || printCompilation) { + if (printCompilation) { start = System.currentTimeMillis(); - allocatedBytesBefore = printAfterCompilation || printCompilation ? threadMXBean.getThreadAllocatedBytes(threadId) : 0L; + allocatedBytesBefore = printCompilation ? threadMXBean.getThreadAllocatedBytes(threadId) : 0L; } else { start = 0L; allocatedBytesBefore = 0L; } + CompilationResult compResult = null; final long startTime = System.currentTimeMillis(); - CompilationResult compResult = aotBackend.compileMethod(method); + SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection(); + try (DebugContext debug = DebugContext.create(graalOptions, new GraalDebugHandlersFactory(snippetReflection)); Activation a = debug.activate()) { + compResult = aotBackend.compileMethod(method, debug); + } final long endTime = System.currentTimeMillis(); - if (printAfterCompilation || printCompilation) { + if (printCompilation) { final long stop = System.currentTimeMillis(); final int targetCodeSize = compResult != null ? compResult.getTargetCodeSize() : -1; final long allocatedBytesAfter = threadMXBean.getThreadAllocatedBytes(threadId); final long allocatedBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024; - if (printAfterCompilation) { - TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dkB", stop - start, targetCodeSize, allocatedBytes)); - } else if (printCompilation) { - TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dkB", getId(), "", "", "", stop - start, targetCodeSize, allocatedBytes)); - } + TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dkB", stop - start, targetCodeSize, allocatedBytes)); } if (compResult == null) { @@ -141,11 +142,11 @@ public class AOTCompilationTask implements Runnable, Comparable { aotBackend.printCompiledMethod((HotSpotResolvedJavaMethod) method, compResult); } - result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method)); + result = new CompiledMethodInfo(compResult, new AOTHotSpotResolvedJavaMethod((HotSpotResolvedJavaMethod) method, aotBackend.getBackend())); } private String getMethodDescription() { - return String.format("%-6d JVMCI %-70s %-45s %-50s %s", getId(), method.getDeclaringClass().getName(), method.getName(), method.getSignature().toMethodDescriptor(), + return String.format("%-6d aot %s %s", getId(), MiscUtils.uniqueMethodName(method), getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + getEntryBCI() + ") "); } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java index 12a72c42dfa..7b708cb1d9c 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java @@ -31,12 +31,16 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import org.graalvm.compiler.options.OptionValues; + import jdk.vm.ci.meta.ResolvedJavaMethod; public class AOTCompiler { private final Main main; + private final OptionValues graalOptions; + private CompileQueue compileQueue; private final AOTBackend backend; @@ -102,11 +106,13 @@ public class AOTCompiler { /** * @param main + * @param graalOptions * @param aotBackend * @param threads number of compilation threads */ - public AOTCompiler(Main main, AOTBackend aotBackend, final int threads) { + public AOTCompiler(Main main, OptionValues graalOptions, AOTBackend aotBackend, final int threads) { this.main = main; + this.graalOptions = graalOptions; this.compileQueue = new CompileQueue(threads); this.backend = aotBackend; } @@ -146,7 +152,7 @@ public class AOTCompiler { * @param method method to be enqueued */ private void enqueueMethod(AOTCompiledClass aotClass, ResolvedJavaMethod method) { - AOTCompilationTask task = new AOTCompilationTask(main, aotClass, method, backend); + AOTCompilationTask task = new AOTCompilationTask(main, graalOptions, aotClass, method, backend); try { compileQueue.execute(task); } catch (RejectedExecutionException e) { diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java index 865ef46c89a..bff6a5124e1 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTHotSpotResolvedJavaMethod.java @@ -24,6 +24,7 @@ package jdk.tools.jaotc; import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder; import jdk.vm.ci.hotspot.HotSpotCompiledCode; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; @@ -31,9 +32,11 @@ import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; public class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo { private final HotSpotResolvedJavaMethod method; + private final Backend backend; - public AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method) { + public AOTHotSpotResolvedJavaMethod(HotSpotResolvedJavaMethod method, Backend backend) { this.method = method; + this.backend = backend; } public String getSymbolName() { @@ -46,7 +49,7 @@ public class AOTHotSpotResolvedJavaMethod implements JavaMethodInfo { } public HotSpotCompiledCode compiledCode(CompilationResult result) { - return HotSpotCompiledCodeBuilder.createCompiledCode(method, null, result); + return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), method, null, result); } } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java index 1eabbdc3a78..b1cd89975ba 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTStub.java @@ -49,7 +49,7 @@ public class AOTStub implements JavaMethodInfo { } public HotSpotCompiledCode compiledCode(CompilationResult result) { - return HotSpotCompiledCodeBuilder.createCompiledCode(null, null, result); + return HotSpotCompiledCodeBuilder.createCompiledCode(backend.getCodeCache(), null, null, result); } } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java index 159955c6bda..68fdafcc3d2 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java @@ -33,9 +33,9 @@ import jdk.tools.jaotc.binformat.ByteContainer; import jdk.tools.jaotc.binformat.HeaderContainer; import jdk.tools.jaotc.utils.Timer; import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.HotSpotHostBackend; +import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.stubs.Stub; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -123,10 +123,12 @@ class DataBuilder { /** * Prepare data with all compiled classes and stubs. * + * @param debug + * * @throws Exception */ @SuppressWarnings("try") - public void prepareData() throws Exception { + public void prepareData(DebugContext debug) throws Exception { try (Timer t = new Timer(main, "Parsing compiled code")) { /* * Copy compiled code into code section container and calls stubs (PLT trampoline). @@ -141,7 +143,7 @@ class DataBuilder { } } - AOTCompiledClass stubCompiledCode = retrieveStubCode(); + AOTCompiledClass stubCompiledCode = retrieveStubCode(debug); // Free memory! try (Timer t = main.options.verbose ? new Timer(main, "Freeing memory") : null) { @@ -176,17 +178,20 @@ class DataBuilder { /** * Get all stubs from Graal and add them to the code section. + * + * @param debug */ @SuppressWarnings("try") - private AOTCompiledClass retrieveStubCode() { + private AOTCompiledClass retrieveStubCode(DebugContext debug) { ArrayList stubs = new ArrayList<>(); - for (Stub stub : Stub.getStubs()) { - try (Scope scope = Debug.scope("CompileStubs")) { - CompilationResult result = stub.getCompilationResult(backend); + HotSpotForeignCallsProvider foreignCallsProvider = backend.getProviders().getForeignCalls(); + for (Stub stub : foreignCallsProvider.getStubs()) { + try (DebugContext.Scope scope = debug.scope("CompileStubs")) { + CompilationResult result = stub.getCompilationResult(debug, backend); CompiledMethodInfo cm = new CompiledMethodInfo(result, new AOTStub(stub, backend)); stubs.add(cm); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } AOTCompiledClass stubCompiledCode = new AOTCompiledClass(stubs); diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java index d9cb0b27aef..988ebf9c0a4 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java @@ -43,7 +43,7 @@ import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.replacements.HotSpotClassSubstitutions; import org.graalvm.compiler.hotspot.word.MetaspacePointer; import org.graalvm.compiler.replacements.Snippets; -import org.graalvm.compiler.word.WordBase; +import org.graalvm.word.WordBase; public class GraalFilters { private List specialClasses; diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java index 933e91acaf4..42752434950 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java @@ -59,15 +59,23 @@ import jdk.tools.jaotc.collect.jar.JarSourceProvider; import jdk.tools.jaotc.collect.module.ModuleSourceProvider; import jdk.tools.jaotc.utils.Timer; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Activation; +import org.graalvm.compiler.hotspot.CompilerConfigurationFactory; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory; +import org.graalvm.compiler.hotspot.HotSpotGraalOptionValues; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotHostBackend; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import org.graalvm.compiler.runtime.RuntimeProvider; import jdk.vm.ci.meta.MetaAccessProvider; @@ -76,11 +84,6 @@ import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.runtime.JVMCI; public class Main implements LogPrinter { - static { - GeneratePIC.setValue(true); - ImmutableCode.setValue(true); - } - static class BadArgs extends Exception { private static final long serialVersionUID = 1L; final String key; @@ -132,13 +135,10 @@ public class Main implements LogPrinter { abstract void process(Main task, String opt, String arg) throws BadArgs; } - static Option[] recognizedOptions = { new Option(" --output Output file name", true, "--output") { + static Option[] recognizedOptions = {new Option(" --output Output file name", true, "--output") { @Override void process(Main task, String opt, String arg) { String name = arg; - if (name.endsWith(".so")) { - name = name.substring(0, name.length() - ".so".length()); - } task.options.outputName = name; } }, new Option(" --class-name List of classes to compile", true, "--class-name", "--classname") { @@ -175,7 +175,7 @@ public class Main implements LogPrinter { }, new Option(" --compile-for-tiered Generate profiling code for tiered compilation", false, "--compile-for-tiered") { @Override void process(Main task, String opt, String arg) { - TieredAOT.setValue(true); + task.options.tiered = true; } }, new Option(" --compile-with-assertions Compile with java assertions", false, "--compile-with-assertions") { @Override @@ -234,6 +234,11 @@ public class Main implements LogPrinter { void process(Main task, String opt, String arg) { task.options.version = true; } + }, new Option(" --linker-path Full path to linker executable", true, "--linker-path") { + @Override + void process(Main task, String opt, String arg) { + task.options.linkerpath = arg; + } }, new Option(" -J Pass directly to the runtime system", false, "-J") { @Override void process(Main task, String opt, String arg) { @@ -242,9 +247,10 @@ public class Main implements LogPrinter { public static class Options { public List files = new LinkedList<>(); - public String outputName = "unnamed"; + public String outputName = defaultOutputName(); public String methodList; public List sources = new ArrayList<>(); + public String linkerpath = null; public SearchPath searchPath = new SearchPath(); /** @@ -262,6 +268,31 @@ public class Main implements LogPrinter { public boolean help; public boolean version; public boolean compileWithAssertions; + public boolean tiered; + + private static String defaultOutputName() { + String osName = System.getProperty("os.name"); + String name = "unnamed."; + String ext; + + switch (osName) { + case "Linux": + case "SunOS": + ext = "so"; + break; + case "Mac OS X": + ext = "dylib"; + break; + default: + if (osName.startsWith("Windows")) { + ext = "dll"; + } else { + ext = "so"; + } + } + + return name + ext; + } } /* package */final Options options = new Options(); @@ -304,7 +335,7 @@ public class Main implements LogPrinter { printlnInfo("Compiling " + options.outputName + "..."); final long start = System.currentTimeMillis(); if (!run()) { - return EXIT_ABNORMAL; + return EXIT_ABNORMAL; } final long end = System.currentTimeMillis(); printlnInfo("Total time: " + (end - start) + " ms"); @@ -347,6 +378,64 @@ public class Main implements LogPrinter { } } + /** + * Visual Studio supported versions Search Order is: VS2013, VS2015, VS2012 + */ + public enum VSVERSIONS { + VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"), + VS2015("VS140COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\bin\\amd64\\link.exe"), + VS2012("VS110COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 11.0\\VC\\bin\\amd64\\link.exe"); + + private final String envvariable; + private final String wkp; + + VSVERSIONS(String envvariable, String wellknownpath) { + this.envvariable = envvariable; + this.wkp = wellknownpath; + } + + String EnvVariable() { + return envvariable; + } + + String WellKnownPath() { + return wkp; + } + } + + /** + * Search for Visual Studio link.exe Search Order is: VS2013, VS2015, VS2012 + */ + private static String getWindowsLinkPath() { + String link = "\\VC\\bin\\amd64\\link.exe"; + + /** + * First try searching the paths pointed to by the VS environment variables. + */ + for (VSVERSIONS vs : VSVERSIONS.values()) { + String vspath = System.getenv(vs.EnvVariable()); + if (vspath != null) { + File commonTools = new File(vspath); + File vsRoot = commonTools.getParentFile().getParentFile(); + File linkPath = new File(vsRoot, link); + if (linkPath.exists()) + return linkPath.getPath(); + } + } + + /** + * If we didn't find via the VS environment variables, try the well known paths + */ + for (VSVERSIONS vs : VSVERSIONS.values()) { + String wkp = vs.WellKnownPath(); + if (new File(wkp).exists()) { + return wkp; + } + } + + return null; + } + @SuppressWarnings("try") private boolean run() throws Exception { openLog(); @@ -379,7 +468,13 @@ public class Main implements LogPrinter { printInfo(classesToCompile.size() + " classes found"); } - GraalJVMCICompiler graalCompiler = (GraalJVMCICompiler) JVMCI.getRuntime().getCompiler(); + OptionValues graalOptions = HotSpotGraalOptionValues.HOTSPOT_OPTIONS; + // Setting -Dgraal.TieredAOT overrides --compile-for-tiered + if (!TieredAOT.hasBeenSet(graalOptions)) { + graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered); + } + graalOptions = new OptionValues(graalOptions, GeneratePIC, true, ImmutableCode, true); + GraalJVMCICompiler graalCompiler = HotSpotGraalCompilerFactory.createCompiler(JVMCI.getRuntime(), graalOptions, CompilerConfigurationFactory.selectFactory(null, graalOptions)); HotSpotGraalRuntimeProvider runtime = (HotSpotGraalRuntimeProvider) graalCompiler.getGraalRuntime(); HotSpotHostBackend backend = (HotSpotHostBackend) runtime.getCapability(RuntimeProvider.class).getHostBackend(); MetaAccessProvider metaAccess = backend.getProviders().getMetaAccess(); @@ -399,8 +494,9 @@ public class Main implements LogPrinter { System.gc(); } - AOTBackend aotBackend = new AOTBackend(this, backend, filters); - AOTCompiler compiler = new AOTCompiler(this, aotBackend, options.threads); + AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend, filters); + SnippetReflectionProvider snippetReflection = aotBackend.getProviders().getSnippetReflection(); + AOTCompiler compiler = new AOTCompiler(this, graalOptions, aotBackend, options.threads); classes = compiler.compileClasses(classes); GraalHotSpotVMConfig graalHotSpotVMConfig = runtime.getVMConfig(); @@ -416,9 +512,12 @@ public class Main implements LogPrinter { System.gc(); } - BinaryContainer binaryContainer = new BinaryContainer(graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION); + BinaryContainer binaryContainer = new BinaryContainer(graalOptions, graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION); DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer); - dataBuilder.prepareData(); + + try (DebugContext debug = DebugContext.create(graalOptions, new GraalDebugHandlersFactory(snippetReflection)); Activation a = debug.activate()) { + dataBuilder.prepareData(debug); + } // Print information about section sizes printContainerInfo(binaryContainer.getHeaderContainer().getContainer()); @@ -451,8 +550,55 @@ public class Main implements LogPrinter { System.gc(); } - String objectFileName = options.outputName + ".o"; - String libraryFileName = options.outputName + ".so"; + String name = options.outputName; + String objectFileName = name; + + String libraryFileName = name; + + String linkerCmd; + String linkerPath; + String osName = System.getProperty("os.name"); + + switch (osName) { + case "Linux": + if (name.endsWith(".so")) { + objectFileName = name.substring(0, name.length() - ".so".length()); + } + linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; + linkerCmd = linkerPath + " -shared -z noexecstack -o " + libraryFileName + " " + objectFileName; + break; + case "SunOS": + if (name.endsWith(".so")) { + objectFileName = name.substring(0, name.length() - ".so".length()); + } + objectFileName = objectFileName + ".o"; + linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; + linkerCmd = linkerPath + " -shared -o " + libraryFileName + " " + objectFileName; + break; + case "Mac OS X": + if (name.endsWith(".dylib")) { + objectFileName = name.substring(0, name.length() - ".dylib".length()); + } + objectFileName = objectFileName + ".o"; + linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld"; + linkerCmd = linkerPath + " -dylib -o " + libraryFileName + " " + objectFileName; + break; + default: + if (osName.startsWith("Windows")) { + if (name.endsWith(".dll")) { + objectFileName = name.substring(0, name.length() - ".dll".length()); + } + objectFileName = objectFileName + ".obj"; + linkerPath = (options.linkerpath != null) ? options.linkerpath : getWindowsLinkPath(); + if (linkerPath == null) { + throw new InternalError("Can't locate Microsoft Visual Studio amd64 link.exe"); + } + linkerCmd = linkerPath + " /DLL /OPT:NOREF /NOLOGO /NOENTRY" + " /OUT:" + libraryFileName + " " + objectFileName; + break; + } else { + throw new InternalError("Unsupported platform: " + osName); + } + } try (Timer t = new Timer(this, "Creating binary: " + objectFileName)) { binaryContainer.createBinary(objectFileName, JVM_VERSION); @@ -466,7 +612,7 @@ public class Main implements LogPrinter { } try (Timer t = new Timer(this, "Creating shared library: " + libraryFileName)) { - Process p = Runtime.getRuntime().exec("ld -shared -z noexecstack -o " + libraryFileName + " " + objectFileName); + Process p = Runtime.getRuntime().exec(linkerCmd); final int exitCode = p.waitFor(); if (exitCode != 0) { InputStream stderr = p.getErrorStream(); @@ -484,7 +630,7 @@ public class Main implements LogPrinter { } // Make non-executable for all. File libFile = new File(libraryFileName); - if (libFile.exists()) { + if (libFile.exists() && !osName.startsWith("Windows")) { if (!libFile.setExecutable(false, false)) { throw new InternalError("Failed to change attribute for " + libraryFileName + " file"); } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java index 8d9b8439760..7840be5bf2d 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java @@ -31,6 +31,20 @@ public interface ClassSource { return fileName.endsWith(".class") && !fileName.endsWith("module-info.class"); } + static String stripRoot(Path path) { + if (path.getRoot() != null) { + String root = path.getRoot().toString(); + String filename = path.toString().substring(root.length()); + String separator = path.getFileSystem().getSeparator(); + while (filename.startsWith(separator)) { + filename = filename.substring(separator.length()); + } + return filename; + } + + return path.toString(); + } + static String makeClassName(Path path) { String fileName = path.toString(); @@ -38,13 +52,10 @@ public interface ClassSource { throw new IllegalArgumentException("File doesn't end with .class: '" + fileName + "'"); } - int start = 0; - if (fileName.startsWith("/")) { - start = 1; - } + fileName = stripRoot(path); - String className = fileName.substring(start, fileName.length() - ".class".length()); - className = className.replace('/', '.'); + String className = fileName.substring(0, fileName.length() - ".class".length()); + className = className.replace(path.getFileSystem().getSeparator(), "."); return className; } diff --git a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java index 0761c0ae8e1..1ad41cb245c 100644 --- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java +++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/FileSupport.java @@ -46,7 +46,9 @@ public class FileSupport { private URI makeJarFileURI(Path path) { try { - return new URI("jar:file:" + path.toAbsolutePath() + "!/"); + String name = path.toAbsolutePath().toString(); + name = name.replace('\\','/'); + return new URI("jar:file:///" + name + "!/"); } catch (URISyntaxException e) { throw new InternalError(e); } diff --git a/hotspot/src/jdk.aot/unix/native/libjelfshim/jdk_tools_jaotc_jnilibelf_JNILibELFAPI.c b/hotspot/src/jdk.aot/unix/native/libjelfshim/jdk_tools_jaotc_jnilibelf_JNILibELFAPI.c deleted file mode 100644 index b64bc2dfdbc..00000000000 --- a/hotspot/src/jdk.aot/unix/native/libjelfshim/jdk_tools_jaotc_jnilibelf_JNILibELFAPI.c +++ /dev/null @@ -1,526 +0,0 @@ -/* - * Copyright (c) 2016, 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 "jdk_tools_jaotc_jnilibelf_JNILibELFAPI.h" - -// For file open and close -#include -#include -#include -#include -#include -#include - -#include - -// For libelf interfaces -#include -#include - -// Convenience macro to shut the compiler warnings -#ifdef UNUSED -#elif defined(__GNUC__) -# define UNUSED(x) UNUSED_ ## x __attribute__((unused)) -#elif defined(__LCLINT__) -# define UNUSED(x) /*@unused@*/ x -#else -# define UNUSED(x) x -#endif - -/** - * libelfshim version - */ -#ifndef AOT_VERSION_STRING - #error AOT_VERSION_STRING must be defined -#endif - -JNIEXPORT jstring JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elfshim_1version -(JNIEnv* env, jclass UNUSED(c)) { - const char* ver = AOT_VERSION_STRING; - return (*env)->NewStringUTF(env, ver); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1version -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint v) { - return elf_version(v); -} - -/** - * Unbox the Pointer object the encapsulated native address. - */ - -static jlong getNativeAddress(JNIEnv* env, jobject ptrObj) { - jlong nativeAddress = -1; - assert (ptrObj != NULL); - // Get a reference to ptr object's class - jclass ptrClass = (*env)->GetObjectClass(env, ptrObj); - if (ptrClass != NULL) { - // Get the Field ID of the instance variables "address" - jfieldID fidNumber = (*env)->GetFieldID(env, ptrClass, "address", "J"); - if (fidNumber != NULL) { - // Get the long given the Field ID - nativeAddress = (*env)->GetLongField(env, ptrObj, fidNumber); - } - } - // fprintf(stderr, "Native address : %lx\n", nativeAddress); - return nativeAddress; -} - -/** - * Box the nativeAddress as a Pointer object. - */ -static jobject makePointerObject(JNIEnv* env, jlong nativeAddr) { - jobject retObj = NULL; - jclass ptrClass = (*env)->FindClass(env, "jdk/tools/jaotc/jnilibelf/Pointer"); - if (ptrClass != NULL) { - // Call back constructor to allocate a Pointer object, with an int argument - jmethodID constructorId = (*env)->GetMethodID(env, ptrClass, "", "(J)V"); - if (constructorId != NULL) { - retObj = (*env)->NewObject(env, ptrClass, constructorId, nativeAddr); - } - } - return retObj; -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1begin -(JNIEnv* env, jclass UNUSED(class), jint filedes, jint cmd, jobject ptrObj) { - - Elf* elfPtr = NULL; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((elfPtr = elf_begin(filedes, cmd, (Elf *) addr)) == NULL) { - errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_begin()\n"); - } - - return makePointerObject(env, (jlong) elfPtr); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1end -(JNIEnv* env, jclass UNUSED(class), jobject ptrObj) { - - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - return elf_end((Elf *) addr); - } else { - fprintf(stderr, "Failed to get native address to call elf_end()\n"); - return -1; - } -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1kind -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - return elf_kind((Elf *) addr); - } else { - fprintf(stderr, "Failed to get native address to call elf_kind()\n"); - return -1; - } -} -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1flagphdr -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint cmd, jint flags) { - - jlong addr = getNativeAddress(env, ptrObj); - unsigned int retVal = 0; - - if (addr != -1) { - // Call libelf function - if ((retVal = elf_flagphdr((Elf *) addr, cmd, flags)) == 0) { - errx(EX_SOFTWARE, "elf_flagphdr() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_flagphdr()\n"); - } - return retVal; -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1newscn -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - - Elf_Scn* elfSecPtr = NULL; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((elfSecPtr = elf_newscn((Elf *) addr)) == NULL) { - errx(EX_SOFTWARE, "elf_newscn() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_newscn()\n"); - } - - return makePointerObject(env, (jlong) elfSecPtr); -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1newdata -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - - Elf_Data* elfDataPtr = NULL; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((elfDataPtr = elf_newdata((Elf_Scn *) addr)) == NULL) { - errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_newdata()\n"); - } - return makePointerObject(env, (jlong) elfDataPtr); -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf64_1getshdr -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - - Elf64_Shdr* elf64ShdrPtr = NULL; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((elf64ShdrPtr = elf64_getshdr((Elf_Scn *) addr)) == NULL) { - errx(EX_SOFTWARE, "elf64_getshdr() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_getshdr()\n"); - } - return makePointerObject(env, (jlong) elf64ShdrPtr); -} - -JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1update -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint cmd) { - - off_t size = -1; - jlong addr = getNativeAddress(env, ptrObj); - - if (addr != -1) { - // Call libelf function - if ((size = elf_update((Elf*) addr, cmd)) == -1) { - errx(EX_SOFTWARE, "elf_update() failed: %s size (%d) cmd (%d).", elf_errmsg(-1), (int)size, cmd); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_update()\n"); - } - return size; -} - -JNIEXPORT jstring JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1errmsg -(JNIEnv* env, jclass UNUSED(c), jint errno) { - - const char * retPtr = NULL; - // Call libelf function - if ((retPtr = elf_errmsg(errno)) == NULL) { - errx(EX_SOFTWARE, "elf_errmsg() failed: %s.", elf_errmsg(-1)); - } - return (*env)->NewStringUTF(env, retPtr); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_elf_1ndxscn -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj) { - jint secnum = SHN_UNDEF; - jlong addr = getNativeAddress(env, ptrObj); - if (addr != -1) { - // Call libelf function - secnum = elf_ndxscn((Elf_Scn*) addr); - } else { - fprintf(stderr, "Failed to get native address to call elf_ndxscn()\n"); - } - return secnum; -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_gelf_1newehdr -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint elfClass) { - unsigned long int retPtr = 0; - jlong addr = getNativeAddress(env, ptrObj); - if (addr != -1) { - // Call libelf function - if ((retPtr = gelf_newehdr((Elf*) addr, elfClass)) == 0) { - errx(EX_SOFTWARE, "gelf_newehdr() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_newehdr()\n"); - } - return makePointerObject(env, (jlong) retPtr); -} - -JNIEXPORT jobject JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_gelf_1newphdr -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint phnum) { - unsigned long int retPtr = 0; - jlong addr = getNativeAddress(env, ptrObj); - if (addr != -1) { - // Call libelf function - if ((retPtr = gelf_newphdr((Elf*) addr, phnum)) == 0) { - errx(EX_SOFTWARE, "gelf_newphdr() failed: %s.", elf_errmsg(-1)); - } - } else { - fprintf(stderr, "Failed to get native address to call elf_newphdr()\n"); - } - return makePointerObject(env, (jlong) retPtr); -} - - -/* File operations */ - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open_1rw -(JNIEnv * env, jclass UNUSED(class), jstring jfileName) { - int flags = O_RDWR | O_CREAT | O_TRUNC; - int mode = 0666; - int retVal; - const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL); - if (cfileName == NULL) { - return -1; - } - retVal = open(cfileName, flags, mode); - if (retVal < 0) { - err(EX_NOINPUT, "open %s failed", cfileName); - } - (*env)->ReleaseStringUTFChars(env, jfileName, cfileName); - - return retVal; -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open__Ljava_lang_String_2I -(JNIEnv * env, jclass UNUSED(class), jstring jfileName, jint flags) { - int retVal; - const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL); - if (cfileName == NULL) { - return -1; - } - retVal = open(cfileName, flags); - if (retVal < 0) { - err(EX_NOINPUT, "open %s failed", cfileName); - } - (*env)->ReleaseStringUTFChars(env, jfileName, cfileName); - - return retVal; -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_open__Ljava_lang_String_2II -(JNIEnv * env, jclass UNUSED(class), jstring jfileName, jint flags, jint mode) { - int retVal; - const char* cfileName = (*env)->GetStringUTFChars(env, jfileName, NULL); - if (cfileName == NULL) { - return -1; - } - retVal = open(cfileName, flags, mode); - if (retVal < 0) { - err(EX_NOINPUT, "open %s failed", cfileName); - } - (*env)->ReleaseStringUTFChars(env, jfileName, cfileName); - - return retVal; -} - - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_close -(JNIEnv* UNUSED(env), jclass UNUSED(class), jint fd) { - return close(fd); -} - -/** - * Miscellaneous ELF data structure peek-poke functions in - * shim_functions.c. No corresponding .h file exists yet. - * So each function needs to be declared as extern - */ - -extern int size_of_Sym(int elfclass); -extern int size_of_Rel(int elfclass); -extern int size_of_Rela(int elfclass); - -extern void ehdr_set_data_encoding(void * ehdr, int val); -extern void set_Ehdr_e_machine(int elfclass, void * structPtr, int val); -extern void set_Ehdr_e_type(int elfclass, void * structPtr, int val); -extern void set_Ehdr_e_version(int elfclass, void * structPtr, int val); -extern void set_Ehdr_e_shstrndx(int elfclass, void * structPtr, int val); - -extern void phdr_set_type_self(int elfclass, void * ehdr, void * phdr); -extern void phdr_set_type_self(int elfclass, void * ehdr, void * phdr); - -extern void set_Shdr_sh_name(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_type(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_flags(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_entsize(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_link(int elfclass, void* structPtr, int val); -extern void set_Shdr_sh_info(int elfclass, void* structPtr, int val); - -extern void set_Data_d_align(void* structPtr, int val); -extern void set_Data_d_off(void* structPtr, int val); -extern void set_Data_d_buf(void* structPtr, void* val); -extern void set_Data_d_type(void* structPtr, int val); -extern void set_Data_d_size(void* structPtr, int val); -extern void set_Data_d_version(void* structPtr, int val); - -extern void* create_sym_entry(int elfclass, int index, int type, int bind, - int shndx, int size, int value); -extern void * create_reloc_entry(int elfclass, int roffset, int symtabIdx, - int relocType, int raddend, int reloca); - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Sym -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) { - return size_of_Sym(elfClass); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Rela -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) { - return size_of_Rela(elfClass); -} - -JNIEXPORT jint JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_size_1of_1Rel -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass) { - return size_of_Rel(elfClass); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_ehdr_1set_1data_1encoding -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* ehdr = (void*) getNativeAddress(env, ptrObj); - ehdr_set_data_encoding(ehdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1machine -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* ehdr = (void*) getNativeAddress(env, ptrObj); - set_Ehdr_e_machine(elfClass, ehdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1type -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* ehdr = (void*) getNativeAddress(env, ptrObj); - set_Ehdr_e_type(elfClass, ehdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1version -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* ehdr = (void*) getNativeAddress(env, ptrObj); - set_Ehdr_e_version(elfClass, ehdr, val); -} -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Ehdr_1e_1shstrndx -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Ehdr_e_shstrndx(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_phdr_1set_1type_1self -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ehdrPtr, jobject phdrPtr) { - void* ehdr = (void*) getNativeAddress(env, ehdrPtr); - void* phdr = (void*) getNativeAddress(env, phdrPtr); - phdr_set_type_self(elfClass, ehdr, phdr); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1name -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_name(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1type -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_type(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1flags -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_flags(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1entsize -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_entsize(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1info -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_info(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Shdr_1sh_1link -(JNIEnv* env, jclass UNUSED(c), jint elfClass, jobject ptrObj, jint val) { - void* shdr = (void*) getNativeAddress(env, ptrObj); - set_Shdr_sh_link(elfClass, shdr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1align -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_align(dptr, val); -} - - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1off -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_off(dptr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1buf -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jobject bufPtr) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - void* bptr = (void*) getNativeAddress(env, bufPtr); - set_Data_d_buf(dptr, bptr); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1type -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_type(dptr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1size -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_size(dptr, val); -} - -JNIEXPORT void JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_set_1Data_1d_1version -(JNIEnv* env, jclass UNUSED(c), jobject ptrObj, jint val) { - void* dptr = (void*) getNativeAddress(env, ptrObj); - set_Data_d_version(dptr, val); -} - -JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_create_1sym_1entry -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass, jint index, jint type, - jint bind, jint shndx, jint size, jint value) { - void * retVal = create_sym_entry(elfClass, index, type, bind, - shndx, size, value); - return (jlong)retVal; -} - -JNIEXPORT jlong JNICALL Java_jdk_tools_jaotc_jnilibelf_JNILibELFAPI_create_1reloc_1entry -(JNIEnv* UNUSED(env), jclass UNUSED(c), jint elfClass, jint roffset, - jint symTabIdx, jint relocType, jint raddend, jint reloca) { - void * retVal = create_reloc_entry(elfClass, roffset, symTabIdx, - relocType, raddend, reloca); - return (jlong)retVal; -} - diff --git a/hotspot/src/jdk.aot/unix/native/libjelfshim/shim_functions.c b/hotspot/src/jdk.aot/unix/native/libjelfshim/shim_functions.c deleted file mode 100644 index e405b0d26c0..00000000000 --- a/hotspot/src/jdk.aot/unix/native/libjelfshim/shim_functions.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (c) 2016, 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 -#include -#include - -/** - * TODO: This is an intial and crude attempt to access structure - * fields of some ELF structrures. Need to figure out a way to access the - * given field of a given structure instead of writing one shim function - * per access of each of the structure field. - **/ - -#define STRINGIFYHELPER(x) #x -#define STRINGIFY(x) STRINGIFYHELPER(x) -#define FUNC_NAME(S, F) set_ ## S ## _ ## F -#define CAST_STRUCT(S, F) ((Elf_ ## S *) structPtr) -#define CAST_STRUCT32(S, F) ((Elf32_ ## S *) structPtr) -#define CAST_STRUCT64(S, F) ((Elf64_ ## S *) structPtr) -#define ACCESS_FIELD(S, F) CAST_STRUCT(S, F)-> F -#define ACCESS_FIELD32(S, F) CAST_STRUCT32(S, F)-> F -#define ACCESS_FIELD64(S, F) CAST_STRUCT64(S, F)-> F - -/* - Example: - SET_TYPE_BASED_FIELD(Ehdr, e_machine, int) - expands to - set_Ehdr_e_machine(int elfclass, void * strPtr, int val) { -} -*/ - -#define SET_TYPE_BASED_FIELD(S, F, T) \ - void FUNC_NAME(S, F)(int elfclass, void * structPtr, T val) { \ - if (elfclass == ELFCLASS32) { \ - ACCESS_FIELD32(S, F) = val; \ - } else if (elfclass == ELFCLASS64) { \ - ACCESS_FIELD64(S, F) = val; \ - } else { \ - printf("%s: Unknown ELF Class %d provided\n", STRINGIFY(FUNC_NAME(S, F)), elfclass); \ - } \ - return; \ -} - -/* - Example: - SET_FIELD(Ehdr, e_machine, int) - expands to - set_Ehdr_e_machine(void * strPtr, int val) { -} -*/ - -#define SET_FIELD(S, F, T) \ - void FUNC_NAME(S, F)(void * structPtr, T val) { \ - ACCESS_FIELD(S, F) = val; \ - return; \ -} - -int size_of_Sym(int elfclass) { - if (elfclass == ELFCLASS32) { - return sizeof(Elf32_Sym); - } else if (elfclass == ELFCLASS64) { - return sizeof(Elf64_Sym); - } else { - printf("Unknown ELF Class %d provided\n", elfclass); - } - return -1; -} - -int size_of_Rela(int elfclass) { - if (elfclass == ELFCLASS32) { - return sizeof(Elf32_Rela); - } else if (elfclass == ELFCLASS64) { - return sizeof(Elf64_Rela); - } else { - printf("Unknown ELF Class %d provided\n", elfclass); - } - return -1; -} - -int size_of_Rel(int elfclass) { - if (elfclass == ELFCLASS32) { - return sizeof(Elf32_Rel); - } else if (elfclass == ELFCLASS64) { - return sizeof(Elf64_Rel); - } else { - printf("Unknown ELF Class %d provided\n", elfclass); - } - return -1; -} - -/* ELF Header field access */ - -void ehdr_set_data_encoding(void * ehdr, int val) { - ((Elf32_Ehdr *) ehdr)->e_ident[EI_DATA] = val; - return; -} - -SET_TYPE_BASED_FIELD(Ehdr, e_machine, int) -SET_TYPE_BASED_FIELD(Ehdr, e_type, int) -SET_TYPE_BASED_FIELD(Ehdr, e_version, int) -SET_TYPE_BASED_FIELD(Ehdr, e_shstrndx, int) - -/* Data descriptor field access */ -SET_FIELD(Data, d_align, int) -SET_FIELD(Data, d_off, int) -SET_FIELD(Data, d_buf, void*) -SET_FIELD(Data, d_type, int) -SET_FIELD(Data, d_size, int) -SET_FIELD(Data, d_version, int) - -/* Section Header Access functions */ -SET_TYPE_BASED_FIELD(Shdr, sh_name, int) -SET_TYPE_BASED_FIELD(Shdr, sh_type, int) -SET_TYPE_BASED_FIELD(Shdr, sh_flags, int) -SET_TYPE_BASED_FIELD(Shdr, sh_entsize, int) -SET_TYPE_BASED_FIELD(Shdr, sh_link, int) -SET_TYPE_BASED_FIELD(Shdr, sh_info, int) - -/* Set the Program Header to be of PH_PHDR type and initialize other - related fields of the program header. -*/ -void phdr_set_type_self(int elfclass, void * ehdr, void * phdr) { - if (elfclass == ELFCLASS32) { - Elf32_Ehdr * ehdr32 = (Elf32_Ehdr *) ehdr; - Elf32_Phdr * phdr32 = (Elf32_Phdr *) phdr; - phdr32->p_type = PT_PHDR; - phdr32->p_offset = ehdr32->e_phoff; - phdr32->p_filesz = elf32_fsize(ELF_T_PHDR, 1, EV_CURRENT); - } else if (elfclass == ELFCLASS64) { - Elf64_Ehdr * ehdr64 = (Elf64_Ehdr *) ehdr; - Elf64_Phdr * phdr64 = (Elf64_Phdr *) phdr; - phdr64->p_type = PT_PHDR; - phdr64->p_offset = ehdr64->e_phoff; - phdr64->p_filesz = elf64_fsize(ELF_T_PHDR, 1, EV_CURRENT); - } else { - printf("phdr_set_type_self: Unknown ELF Class %d provided\n", elfclass); - } - return; -} - -/* - Create symbol table entry with given type and binding -*/ -void * create_sym_entry(int elfclass, int index, int type, int bind, - int shndx, int size, int value) { - void * symentry = NULL; - if (elfclass == ELFCLASS32) { - Elf32_Sym * sym32 = (Elf32_Sym *) malloc(sizeof(Elf32_Sym)); - sym32->st_name = index; - sym32->st_value = value; - sym32->st_size = size; - sym32->st_info = ELF32_ST_INFO(bind, type); - sym32->st_other = 0; // TODO: Add an argument to get this value ?? - sym32->st_shndx = shndx; - symentry = sym32; - } else if (elfclass == ELFCLASS64) { - Elf64_Sym * sym64 = (Elf64_Sym *) malloc(sizeof(Elf64_Sym)); - sym64->st_name = index; - sym64->st_value = value; - sym64->st_size = size; - sym64->st_info = ELF64_ST_INFO(bind, type); - sym64->st_other = 0; // TODO: Add an argument to get this value ?? - sym64->st_shndx = shndx; - symentry = sym64; - } else { - printf("create_sym_entry: Unknown ELF Class %d provided\n", elfclass); - } - return (void *) symentry; -} - -// Create a reloc (or reloca entry if argument reloca is non-zero) -void * create_reloc_entry(int elfclass, int roffset, int symtabIdx, - int relocType, int raddend, int reloca) { - void * relocentry = NULL; - if (elfclass == ELFCLASS32) { - if (reloca) { - Elf32_Rela * rela32 = (Elf32_Rela *) malloc(sizeof(Elf32_Rela)); - rela32->r_offset = roffset; - rela32->r_info = ELF32_R_INFO(symtabIdx, relocType); - rela32->r_addend = raddend; - relocentry = rela32; - } else { - Elf32_Rel * rel32 = (Elf32_Rel *) malloc(sizeof(Elf32_Rel)); - rel32->r_offset = roffset; - rel32->r_info = ELF32_R_INFO(symtabIdx, relocType); - relocentry = rel32; - } - } else if (elfclass == ELFCLASS64) { - if (reloca) { - Elf64_Rela * rela64 = (Elf64_Rela *) malloc(sizeof(Elf64_Rela)); - rela64->r_offset = roffset; - rela64->r_info = ELF64_R_INFO(symtabIdx, relocType); - rela64->r_addend = raddend; - relocentry = rela64; - } else { - Elf64_Rel * rel64 = (Elf64_Rel *) malloc(sizeof(Elf64_Rel)); - rel64->r_offset = roffset; - rel64->r_info = ELF64_R_INFO(symtabIdx, relocType); - relocentry = rel64; - } - } else { - printf("create_reloc_entry: Unknown ELF Class %d provided\n", elfclass); - } - return (void *) relocentry; -} diff --git a/hotspot/src/jdk.hotspot.agent/doc/jsdb.html b/hotspot/src/jdk.hotspot.agent/doc/jsdb.html index e691bb9cb3c..b42ccd03bb4 100644 --- a/hotspot/src/jdk.hotspot.agent/doc/jsdb.html +++ b/hotspot/src/jdk.hotspot.agent/doc/jsdb.html @@ -1108,11 +1108,6 @@ or not. calls callback with Klass and initiating loader (Oop) for System dictionary entry. -
    forEachPrimArrayKlass(callback)
    -
    -calls callback with Klass and initiating loader (Oop) for each -primitive array Klass in the system. -
    findInstanceKlass(name)
    finds the first instance klass with given name from System dictionary diff --git a/hotspot/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m b/hotspot/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m index d2a52c22b3a..189353eef2d 100644 --- a/hotspot/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m +++ b/hotspot/src/jdk.hotspot.agent/macosx/native/libsaproc/MacosxDebuggerLocal.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -689,8 +689,8 @@ static bool ptrace_waitpid(pid_t pid) { // attach to a process/thread specified by "pid" static bool ptrace_attach(pid_t pid) { int res; - if ((res = ptrace(PT_ATTACH, pid, 0, 0)) < 0) { - print_error("ptrace(PT_ATTACH, %d) failed with %d\n", pid, res); + if ((res = ptrace(PT_ATTACHEXC, pid, 0, 0)) < 0) { + print_error("ptrace(PT_ATTACHEXC, %d) failed with %d\n", pid, res); return false; } else { return ptrace_waitpid(pid); diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java index ec8b0ac70a9..83a9b05479f 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/CommandProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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 @@ -48,6 +48,7 @@ import sun.jvm.hotspot.code.CodeCacheVisitor; import sun.jvm.hotspot.code.NMethod; import sun.jvm.hotspot.debugger.Address; import sun.jvm.hotspot.debugger.OopHandle; +import sun.jvm.hotspot.classfile.ClassLoaderDataGraph; import sun.jvm.hotspot.memory.SymbolTable; import sun.jvm.hotspot.memory.SystemDictionary; import sun.jvm.hotspot.memory.Universe; @@ -853,8 +854,8 @@ public class CommandProcessor { } else { String s = t.nextToken(); if (s.equals("-a")) { - SystemDictionary sysDict = VM.getVM().getSystemDictionary(); - sysDict.allClassesDo(new SystemDictionary.ClassVisitor() { + ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph(); + cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() { public void visit(Klass k) { if (k instanceof InstanceKlass) { MethodArray methods = ((InstanceKlass)k).getMethods(); @@ -887,8 +888,8 @@ public class CommandProcessor { if (t.countTokens() != 0) { usage(); } else { - SystemDictionary sysDict = VM.getVM().getSystemDictionary(); - sysDict.allClassesDo(new SystemDictionary.ClassVisitor() { + ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph(); + cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() { public void visit(Klass k) { if (k instanceof InstanceKlass && ((InstanceKlass)k).getConstants().getCache() != null) { MethodArray methods = ((InstanceKlass)k).getMethods(); diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java index 947701c9c3b..6423371e263 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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,16 +25,16 @@ package sun.jvm.hotspot.classfile; import java.io.PrintStream; -import java.util.*; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.types.*; public class ClassLoaderData extends VMObject { static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { + VM.registerVMInitializedObserver(new java.util.Observer() { + public void update(java.util.Observable o, Object data) { initialize(VM.getVM().getTypeDataBase()); } }); @@ -44,19 +44,26 @@ public class ClassLoaderData extends VMObject { Type type = db.lookupType("ClassLoaderData"); classLoaderField = type.getOopField("_class_loader"); nextField = type.getAddressField("_next"); - klassesField = type.getAddressField("_klasses"); + klassesField = new MetadataField(type.getAddressField("_klasses"), 0); isAnonymousField = new CIntField(type.getCIntegerField("_is_anonymous"), 0); + dictionaryField = type.getAddressField("_dictionary"); } private static sun.jvm.hotspot.types.OopField classLoaderField; private static AddressField nextField; - private static AddressField klassesField; + private static MetadataField klassesField; private static CIntField isAnonymousField; + private static AddressField dictionaryField; public ClassLoaderData(Address addr) { super(addr); } + public Dictionary dictionary() { + Address tmp = dictionaryField.getValue(); + return (Dictionary) VMObjectFactory.newObject(Dictionary.class, tmp); + } + public static ClassLoaderData instantiateWrapperFor(Address addr) { if (addr == null) { return null; @@ -76,7 +83,30 @@ public class ClassLoaderData extends VMObject { return instantiateWrapperFor(nextField.getValue(getAddress())); } - public Klass getKlasses() { - return (InstanceKlass)Metadata.instantiateWrapperFor(klassesField.getValue(getAddress())); + public Klass getKlasses() { return (Klass)klassesField.getValue(this); } + + /** Lookup an already loaded class. If not found null is returned. */ + public Klass find(Symbol className) { + for (Klass l = getKlasses(); l != null; l = l.getNextLinkKlass()) { + if (className.equals(l.getName())) { + return l; + } + } + return null; + } + + /** Iterate over all klasses - including object, primitive + array klasses */ + public void classesDo(ClassLoaderDataGraph.ClassVisitor v) { + for (Klass l = getKlasses(); l != null; l = l.getNextLinkKlass()) { + v.visit(l); + } + } + + /** Iterate over all klasses in the dictionary, including initiating loader. */ + public void allEntriesDo(ClassLoaderDataGraph.ClassAndLoaderVisitor v) { + for (Klass l = getKlasses(); l != null; l = l.getNextLinkKlass()) { + dictionary().allEntriesDo(v, getClassLoader()); + } } } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderDataGraph.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderDataGraph.java index fbc9a76401d..4408ecb90e7 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderDataGraph.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/classfile/ClassLoaderDataGraph.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package sun.jvm.hotspot.classfile; import java.io.PrintStream; import java.util.*; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.classfile.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.types.*; @@ -52,21 +53,43 @@ public class ClassLoaderDataGraph { return ClassLoaderData.instantiateWrapperFor(headField.getValue()); } - public static interface KlassVisitor { + /** Lookup an already loaded class in any class loader. */ + public Klass find(String className) { + Symbol sym = VM.getVM().getSymbolTable().probe(className); + if (sym == null) return null; + for (ClassLoaderData cld = getClassLoaderGraphHead(); cld != null; cld = cld.next()) { + Klass k = cld.find(sym); + if (k != null) { + return k; + } + } + return null; + } + + /** Interface for iterating through all classes. */ + public static interface ClassVisitor { public void visit(Klass k); } - /** Iterate over all anonymous class loaders and the klasses in those */ - public void allAnonymousKlassesDo(final KlassVisitor v) { - for (ClassLoaderData cl = getClassLoaderGraphHead(); - cl != null; - cl = cl.next()) { - if (cl.getIsAnonymous() == true) { - for (Klass k = cl.getKlasses(); k != null; k = k.getNextLinkKlass()) { - v.visit(k); - } - } + /** Interface for iterating through all classes and their class + loaders in dictionary */ + public static interface ClassAndLoaderVisitor { + public void visit(Klass k, Oop loader); + } + + /** Iterate over all klasses - including object, primitive + array klasses */ + public void classesDo(ClassVisitor v) { + for (ClassLoaderData cld = getClassLoaderGraphHead(); cld != null; cld = cld.next()) { + cld.classesDo(v); } } + /** Iterate over all klasses - including object, primitive + array klasses, pass initiating loader. */ + public void allEntriesDo(ClassAndLoaderVisitor v) { + for (ClassLoaderData cld = getClassLoaderGraphHead(); cld != null; cld = cld.next()) { + cld.allEntriesDo(v); + } + } } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java index f2ae000b8df..84ec0a195ea 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java @@ -71,7 +71,7 @@ public class NMethod extends CompiledMethod { stack. An not_entrant method can be removed when there is no more activations, i.e., when the _stack_traversal_mark is less than current sweep traversal index. */ - private static CIntegerField stackTraversalMarkField; + private static JLongField stackTraversalMarkField; private static CIntegerField compLevelField; @@ -105,7 +105,7 @@ public class NMethod extends CompiledMethod { verifiedEntryPointField = type.getAddressField("_verified_entry_point"); osrEntryPointField = type.getAddressField("_osr_entry_point"); lockCountField = type.getJIntField("_lock_count"); - stackTraversalMarkField = type.getCIntegerField("_stack_traversal_mark"); + stackTraversalMarkField = type.getJLongField("_stack_traversal_mark"); compLevelField = type.getCIntegerField("_comp_level"); pcDescSize = db.lookupType("PcDesc").getSize(); } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/win32/coff/MachineTypes.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/win32/coff/MachineTypes.java index 14c8ee8118d..aaa00e9a5a0 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/win32/coff/MachineTypes.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/win32/coff/MachineTypes.java @@ -39,8 +39,6 @@ public interface MachineTypes { public static final short IMAGE_FILE_MACHINE_ALPHA64 = (short) 0x284; /** Intel 386 or later, and compatible processors. */ public static final short IMAGE_FILE_MACHINE_I386 = (short) 0x14c; - /** Intel IA64 */ - public static final short IMAGE_FILE_MACHINE_IA64 = (short) 0x200; /** Motorola 68000 series. */ public static final short IMAGE_FILE_MACHINE_M68K = (short) 0x268; public static final short IMAGE_FILE_MACHINE_MIPS16 = (short) 0x266; diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java index d9da1570b89..9a714b9c8a9 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeLoadConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -121,14 +121,7 @@ public class BytecodeLoadConstant extends Bytecode { // decide based on the oop type. ConstantPool cpool = method().getConstants(); int cpIndex = poolIndex(); - ConstantPool.CPSlot oop = cpool.getSlotAt(cpIndex); - if (oop.isResolved()) { - return oop.getKlass(); - } else if (oop.isUnresolved()) { - return oop.getSymbol(); - } else { - throw new RuntimeException("should not reach here"); - } + return cpool.getKlassNameAt(cpIndex); } public static BytecodeLoadConstant at(Method method, int bci) { @@ -171,12 +164,12 @@ public class BytecodeLoadConstant extends Bytecode { // tag change from 'unresolved' to 'klass' does not happen atomically. // We just look at the object at the corresponding index and // decide based on the oop type. - ConstantPool.CPSlot obj = cpool.getSlotAt(cpIndex); - if (obj.isResolved()) { - Klass k = obj.getKlass(); + ConstantTag tag = cpool.getTagAt(cpIndex); + if (tag.isKlass()) { + Klass k = cpool.getKlassAt(cpIndex); return ""; - } else if (obj.isUnresolved()) { - Symbol sym = obj.getSymbol(); + } else if (tag.isUnresolvedKlass()) { + Symbol sym = cpool.getKlassNameAt(cpIndex); return ""; } else { throw new RuntimeException("should not reach here"); diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithKlass.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithKlass.java index 7e06cce1779..8ad0aa7e9b3 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithKlass.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/interpreter/BytecodeWithKlass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -37,12 +37,7 @@ public class BytecodeWithKlass extends BytecodeWithCPIndex { } public Symbol getClassName() { - ConstantPool.CPSlot obj = method().getConstants().getSlotAt(index()); - if (obj.isUnresolved()) { - return obj.getSymbol(); - } else { - return obj.getKlass().getName(); - } + return method().getConstants().getKlassNameAt(index()); } public String toString() { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Dictionary.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Dictionary.java index 4c4005428ce..5957f65bcc9 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Dictionary.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Dictionary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -26,12 +26,13 @@ package sun.jvm.hotspot.memory; import java.util.*; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.classfile.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.types.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.utilities.*; -public class Dictionary extends TwoOopHashtable { +public class Dictionary extends sun.jvm.hotspot.utilities.Hashtable { static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -55,56 +56,32 @@ public class Dictionary extends TwoOopHashtable { return DictionaryEntry.class; } - /** Iterate over all klasses in dictionary; just the classes from - declaring class loaders */ - public void classesDo(SystemDictionary.ClassVisitor v) { - ObjectHeap heap = VM.getVM().getObjectHeap(); + /** All classes, and their initiating class loader, passed in. */ + public void allEntriesDo(ClassLoaderDataGraph.ClassAndLoaderVisitor v, Oop loader) { int tblSize = tableSize(); for (int index = 0; index < tblSize; index++) { for (DictionaryEntry probe = (DictionaryEntry) bucket(index); probe != null; - probe = (DictionaryEntry) probe.next()) { + probe = (DictionaryEntry) probe.next()) { Klass k = probe.klass(); - if (heap.equal(probe.loader(), ((InstanceKlass) k).getClassLoader())) { - v.visit(k); - } + v.visit(k, loader); } } } - /** All classes, and their class loaders */ - public void classesDo(SystemDictionary.ClassAndLoaderVisitor v) { - int tblSize = tableSize(); - for (int index = 0; index < tblSize; index++) { - for (DictionaryEntry probe = (DictionaryEntry) bucket(index); probe != null; - probe = (DictionaryEntry) probe.next()) { - Klass k = probe.klass(); - v.visit(k, probe.loader()); - } - } - } - - public Klass find(int index, long hash, Symbol className, Oop classLoader, Oop protectionDomain) { - DictionaryEntry entry = getEntry(index, hash, className, classLoader); - if (entry != null && entry.isValidProtectionDomain(protectionDomain)) { - return entry.klass(); - } - return null; - } - // - Internals only below this point - private DictionaryEntry getEntry(int index, long hash, Symbol className, Oop classLoader) { + private DictionaryEntry getEntry(int index, long hash, Symbol className) { for (DictionaryEntry entry = (DictionaryEntry) bucket(index); entry != null; entry = (DictionaryEntry) entry.next()) { - if (entry.hash() == hash && entry.equals(className, classLoader)) { + if (entry.hash() == hash && entry.equals(className)) { return entry; } } return null; } - public boolean contains(Klass c, Oop classLoader) { - long hash = computeHash(c.getName(), classLoader); + public boolean contains(Klass c) { + long hash = computeHash(c.getName()); int index = hashToIndex(hash); for (DictionaryEntry entry = (DictionaryEntry) bucket(index); entry != null; diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/DictionaryEntry.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/DictionaryEntry.java index 3d4a9f6392e..c6d9c331bb0 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/DictionaryEntry.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/DictionaryEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -43,28 +43,6 @@ public class DictionaryEntry extends sun.jvm.hotspot.utilities.HashtableEntry { private static synchronized void initialize(TypeDataBase db) { Type type = db.lookupType("DictionaryEntry"); - pdSetField = type.getAddressField("_pd_set"); - loaderDataField = type.getAddressField("_loader_data"); - } - - // Fields - private static AddressField pdSetField; - private static AddressField loaderDataField; - - // Accessors - - public ProtectionDomainEntry pdSet() { - Address tmp = pdSetField.getValue(addr); - return (ProtectionDomainEntry) VMObjectFactory.newObject( - ProtectionDomainEntry.class, tmp); - } - - public Oop loader() { - return loaderData().getClassLoader(); - } - - public ClassLoaderData loaderData() { - return ClassLoaderData.instantiateWrapperFor(loaderDataField.getValue(addr)); } public Klass klass() { @@ -75,38 +53,9 @@ public class DictionaryEntry extends sun.jvm.hotspot.utilities.HashtableEntry { super(addr); } - public boolean equals(Symbol className, Oop classLoader) { + public boolean equals(Symbol className) { InstanceKlass ik = (InstanceKlass) klass(); - Oop loader = loader(); - if (! ik.getName().equals(className)) { - return false; - } else { - return (loader == null)? (classLoader == null) : - (loader.equals(classLoader)); - } - } - - public boolean isValidProtectionDomain(Oop protectionDomain) { - if (protectionDomain == null) { - return true; - } else { - return containsProtectionDomain(protectionDomain); - } - } - - public boolean containsProtectionDomain(Oop protectionDomain) { - InstanceKlass ik = (InstanceKlass) klass(); - // Currently unimplemented and not used. - // if (protectionDomain.equals(ik.getJavaMirror().getProtectionDomain())) { - // return true; // Succeeds trivially - // } - for (ProtectionDomainEntry current = pdSet(); current != null; - current = current.next()) { - if (protectionDomain.equals(current.protectionDomain())) { - return true; - } - } - return false; + return ik.getName().equals(className); } /* covariant return type :-( diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/LoaderConstraintEntry.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/LoaderConstraintEntry.java deleted file mode 100644 index 248308baa7f..00000000000 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/LoaderConstraintEntry.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.memory; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.utilities.*; - -public class LoaderConstraintEntry extends sun.jvm.hotspot.utilities.HashtableEntry { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("LoaderConstraintEntry"); - nameField = type.getAddressField("_name"); - numLoadersField = type.getCIntegerField("_num_loaders"); - maxLoadersField = type.getCIntegerField("_max_loaders"); - loadersField = type.getAddressField("_loaders"); - } - - // Fields - private static AddressField nameField; - private static CIntegerField numLoadersField; - private static CIntegerField maxLoadersField; - private static AddressField loadersField; - - // Accessors - - public Symbol name() { - return Symbol.create(nameField.getValue(addr)); - } - - public int numLoaders() { - return (int) numLoadersField.getValue(addr); - } - - public int maxLoaders() { - return (int) maxLoadersField.getValue(addr); - } - - public Oop initiatingLoader(int i) { - if (Assert.ASSERTS_ENABLED) { - Assert.that(i >= 0 && i < numLoaders(), "invalid index"); - } - Address loaders = loadersField.getValue(addr); - OopHandle loader = loaders.addOffsetToAsOopHandle(i * VM.getVM().getOopSize()); - return VM.getVM().getObjectHeap().newOop(loader); - } - - public LoaderConstraintEntry(Address addr) { - super(addr); - } - - /* covariant return type :-( - public LoaderConstraintEntry next() { - return (LoaderConstraintEntry) super.next(); - } - For now, let the caller cast it .. - */ -} diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/LoaderConstraintTable.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/LoaderConstraintTable.java deleted file mode 100644 index d2afad35f31..00000000000 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/LoaderConstraintTable.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.memory; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.utilities.*; - -public class LoaderConstraintTable extends TwoOopHashtable { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("LoaderConstraintTable"); - } - - public LoaderConstraintTable(Address addr) { - super(addr); - } - - // this is overriden here so that Hashtable.bucket will return - // object of LoaderConstraintEntry.class - protected Class getHashtableEntryClass() { - return LoaderConstraintEntry.class; - } -} diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/PlaceholderEntry.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/PlaceholderEntry.java deleted file mode 100644 index 5f396b787c1..00000000000 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/PlaceholderEntry.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.memory; - -import java.util.*; -import sun.jvm.hotspot.classfile.ClassLoaderData; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.types.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.utilities.*; - -public class PlaceholderEntry extends sun.jvm.hotspot.utilities.HashtableEntry { - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("PlaceholderEntry"); - loaderDataField = type.getAddressField("_loader_data"); - } - - // Field - private static AddressField loaderDataField; - - // Accessor - public Oop loader() { - return loaderData().getClassLoader(); - } - - public ClassLoaderData loaderData() { - return ClassLoaderData.instantiateWrapperFor(loaderDataField.getValue(addr)); - } - - public PlaceholderEntry(Address addr) { - super(addr); - } - - public Symbol klass() { - return Symbol.create(literalValue()); - } - - /* covariant return type :-( - public PlaceholderEntry next() { - return (PlaceholderEntry) super.next(); - } - For now, let the caller cast it .. - */ -} diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/PlaceholderTable.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/PlaceholderTable.java deleted file mode 100644 index 72d354b56d5..00000000000 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/PlaceholderTable.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.memory; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.utilities.*; - -public class PlaceholderTable extends TwoOopHashtable { - public PlaceholderTable(Address addr) { - super(addr); - } - - // this is overriden here so that Hashtable.bucket will return - // object of PlacholderEntry.class - protected Class getHashtableEntryClass() { - return PlaceholderEntry.class; - } - - /** All array classes of primitive type, and their class loaders */ - public void primArrayClassesDo(SystemDictionary.ClassAndLoaderVisitor v) { - ObjectHeap heap = VM.getVM().getObjectHeap(); - int tblSize = tableSize(); - for (int index = 0; index < tblSize; index++) { - for (PlaceholderEntry probe = (PlaceholderEntry) bucket(index); probe != null; - probe = (PlaceholderEntry) probe.next()) { - Symbol sym = probe.klass(); - // array of primitive arrays are stored in system dictionary as placeholders - FieldType ft = new FieldType(sym); - if (ft.isArray()) { - FieldType.ArrayInfo info = ft.getArrayInfo(); - if (info.elementBasicType() != BasicType.getTObject()) { - Klass arrayKlass = heap.typeArrayKlassObj(info.elementBasicType()); - arrayKlass = arrayKlass.arrayKlassOrNull(info.dimension()); - v.visit(arrayKlass, probe.loader()); - } - } - } - } - } -} diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/ProtectionDomainCacheEntry.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/ProtectionDomainCacheEntry.java deleted file mode 100644 index 2c9e736ec4a..00000000000 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/ProtectionDomainCacheEntry.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.memory; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.types.*; - -public class ProtectionDomainCacheEntry extends VMObject { - private static sun.jvm.hotspot.types.OopField protectionDomainField; - - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("ProtectionDomainCacheEntry"); - protectionDomainField = type.getOopField("_literal"); - } - - public ProtectionDomainCacheEntry(Address addr) { - super(addr); - } - - public Oop protectionDomain() { - return VM.getVM().getObjectHeap().newOop(protectionDomainField.getValue(addr)); - } -} diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/ProtectionDomainEntry.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/ProtectionDomainEntry.java deleted file mode 100644 index 27aa4e9f43b..00000000000 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/ProtectionDomainEntry.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.memory; - -import java.util.*; -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.oops.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.types.*; - -public class ProtectionDomainEntry extends VMObject { - private static AddressField nextField; - private static AddressField pdCacheField; - - static { - VM.registerVMInitializedObserver(new Observer() { - public void update(Observable o, Object data) { - initialize(VM.getVM().getTypeDataBase()); - } - }); - } - - private static synchronized void initialize(TypeDataBase db) { - Type type = db.lookupType("ProtectionDomainEntry"); - - nextField = type.getAddressField("_next"); - pdCacheField = type.getAddressField("_pd_cache"); - } - - public ProtectionDomainEntry(Address addr) { - super(addr); - } - - public ProtectionDomainEntry next() { - return (ProtectionDomainEntry) VMObjectFactory.newObject(ProtectionDomainEntry.class, nextField.getValue(addr)); - } - - public Oop protectionDomain() { - ProtectionDomainCacheEntry pd_cache = (ProtectionDomainCacheEntry) - VMObjectFactory.newObject(ProtectionDomainCacheEntry.class, pdCacheField.getValue(addr)); - return pd_cache.protectionDomain(); - } -} diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java index b2beedb6977..d461850a8cd 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/SystemDictionary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -26,15 +26,13 @@ package sun.jvm.hotspot.memory; import java.util.*; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.classfile.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.types.*; public class SystemDictionary { - private static AddressField dictionaryField; private static AddressField sharedDictionaryField; - private static AddressField placeholdersField; - private static AddressField loaderConstraintTableField; private static sun.jvm.hotspot.types.OopField javaSystemLoaderField; private static AddressField objectKlassField; @@ -56,10 +54,7 @@ public class SystemDictionary { private static synchronized void initialize(TypeDataBase db) { Type type = db.lookupType("SystemDictionary"); - dictionaryField = type.getAddressField("_dictionary"); sharedDictionaryField = type.getAddressField("_shared_dictionary"); - placeholdersField = type.getAddressField("_placeholders"); - loaderConstraintTableField = type.getAddressField("_loader_constraints"); javaSystemLoaderField = type.getOopField("_java_system_loader"); objectKlassField = type.getAddressField(WK_KLASS("Object_klass")); @@ -81,26 +76,11 @@ public class SystemDictionary { return (kname+"_knum"); } - public Dictionary dictionary() { - Address tmp = dictionaryField.getValue(); - return (Dictionary) VMObjectFactory.newObject(Dictionary.class, tmp); - } - public Dictionary sharedDictionary() { Address tmp = sharedDictionaryField.getValue(); return (Dictionary) VMObjectFactory.newObject(Dictionary.class, tmp); } - public PlaceholderTable placeholders() { - Address tmp = placeholdersField.getValue(); - return (PlaceholderTable) VMObjectFactory.newObject(PlaceholderTable.class, tmp); - } - - public LoaderConstraintTable constraints() { - Address tmp = placeholdersField.getValue(); - return (LoaderConstraintTable) VMObjectFactory.newObject(LoaderConstraintTable.class, tmp); - } - // few well known classes -- not all are added here. // add more if needed. public static InstanceKlass getThreadKlass() { @@ -132,8 +112,8 @@ public class SystemDictionary { } public InstanceKlass getAbstractOwnableSynchronizerKlass() { - return (InstanceKlass) find("java/util/concurrent/locks/AbstractOwnableSynchronizer", - null, null); + ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph(); + return (InstanceKlass) cldg.find("java/util/concurrent/locks/AbstractOwnableSynchronizer"); } public static Oop javaSystemLoader() { @@ -143,60 +123,4 @@ public class SystemDictionary { private static Oop newOop(OopHandle handle) { return VM.getVM().getObjectHeap().newOop(handle); } - - /** Lookup an already loaded class. If not found null is returned. */ - public Klass find(String className, Oop classLoader, Oop protectionDomain) { - Symbol sym = VM.getVM().getSymbolTable().probe(className); - if (sym == null) return null; - return find(sym, classLoader, protectionDomain); - } - - /** Lookup an already loaded class. If not found null is returned. */ - public Klass find(Symbol className, Oop classLoader, Oop protectionDomain) { - Dictionary dict = dictionary(); - long hash = dict.computeHash(className, classLoader); - int index = dict.hashToIndex(hash); - return dict.find(index, hash, className, classLoader, protectionDomain); - } - - /** Interface for iterating through all classes in dictionary */ - public static interface ClassVisitor { - public void visit(Klass k); - } - - /** Interface for iterating through all classes and their class - loaders in dictionary */ - public static interface ClassAndLoaderVisitor { - public void visit(Klass k, Oop loader); - } - - /** Iterate over all klasses - including object, primitive - array klasses */ - public void allClassesDo(final ClassVisitor v) { - ClassVisitor visitor = new ClassVisitor() { - public void visit(Klass k) { - for (Klass l = k; l != null; l = l.arrayKlassOrNull()) { - v.visit(l); - } - } - }; - classesDo(visitor); - VM.getVM().getUniverse().basicTypeClassesDo(visitor); - } - - /** Iterate over all klasses in dictionary; just the classes from - declaring class loaders */ - public void classesDo(ClassVisitor v) { - dictionary().classesDo(v); - } - - /** All classes, and their class loaders */ - public void classesDo(ClassAndLoaderVisitor v) { - dictionary().classesDo(v); - } - - /** All array classes of primitive type, and their class loaders */ - public void primArrayClassesDo(ClassAndLoaderVisitor v) { - placeholders().primArrayClassesDo(v); - } } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java index 637bdc5ecd5..23fc9f6ce24 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/Universe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -164,18 +164,6 @@ public class Universe { return newOop(systemThreadGroupField.getValue()); } - // iterate through the single dimensional primitive array klasses - // refer to basic_type_classes_do(void f(Klass*)) in universe.cpp - public void basicTypeClassesDo(SystemDictionary.ClassVisitor visitor) { - visitor.visit(new TypeArrayKlass(boolArrayKlassField.getValue())); - visitor.visit(new TypeArrayKlass(byteArrayKlassField.getValue())); - visitor.visit(new TypeArrayKlass(charArrayKlassField.getValue())); - visitor.visit(new TypeArrayKlass(intArrayKlassField.getValue())); - visitor.visit(new TypeArrayKlass(shortArrayKlassField.getValue())); - visitor.visit(new TypeArrayKlass(longArrayKlassField.getValue())); - visitor.visit(new TypeArrayKlass(singleArrayKlassField.getValue())); - visitor.visit(new TypeArrayKlass(doubleArrayKlassField.getValue())); - } public void print() { printOn(System.out); } public void printOn(PrintStream tty) { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java index fc1f461acd4..c7285ed316d 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -35,30 +35,35 @@ import sun.jvm.hotspot.utilities.*; // as described in the class file public class ConstantPool extends Metadata implements ClassConstants { - public class CPSlot { + private class CPSlot { private Address ptr; CPSlot(Address ptr) { this.ptr = ptr; } - CPSlot(Symbol sym) { - this.ptr = sym.getAddress().orWithMask(1); - } - - public boolean isResolved() { - return (ptr.minus(null) & 1) == 0; - } - public boolean isUnresolved() { - return (ptr.minus(null) & 1) == 1; - } public Symbol getSymbol() { - if (!isUnresolved()) throw new InternalError("not a symbol"); - return Symbol.create(ptr.xorWithMask(1)); + // (Lowest bit == 1) -> this is an pseudo string. + return Symbol.create(ptr.andWithMask(~1)); + } + } + private class CPKlassSlot { + private int name_index; + private int resolved_klass_index; + private static final int temp_resolved_klass_index = 0xffff; + + public CPKlassSlot(int n, int rk) { + name_index = n; + resolved_klass_index = rk; + } + public int getNameIndex() { + return name_index; + } + public int getResolvedKlassIndex() { + if (Assert.ASSERTS_ENABLED) { + Assert.that(resolved_klass_index != temp_resolved_klass_index, "constant pool merging was incomplete"); } - public Klass getKlass() { - if (!isResolved()) throw new InternalError("not klass"); - return (Klass)Metadata.instantiateWrapperFor(ptr); + return resolved_klass_index; } } @@ -84,8 +89,7 @@ public class ConstantPool extends Metadata implements ClassConstants { cache = type.getAddressField("_cache"); poolHolder = new MetadataField(type.getAddressField("_pool_holder"), 0); length = new CIntField(type.getCIntegerField("_length"), 0); - resolvedReferences = type.getAddressField("_resolved_references"); - referenceMap = type.getAddressField("_reference_map"); + resolved_klasses = type.getAddressField("_resolved_klasses"); headerSize = type.getSize(); elementSize = 0; // fetch constants: @@ -103,10 +107,9 @@ public class ConstantPool extends Metadata implements ClassConstants { private static AddressField tags; private static AddressField operands; private static AddressField cache; + private static AddressField resolved_klasses; private static MetadataField poolHolder; private static CIntField length; // number of elements in oop - private static AddressField resolvedReferences; - private static AddressField referenceMap; private static long headerSize; private static long elementSize; @@ -124,17 +127,14 @@ public class ConstantPool extends Metadata implements ClassConstants { public InstanceKlass getPoolHolder() { return (InstanceKlass)poolHolder.getValue(this); } public int getLength() { return (int)length.getValue(getAddress()); } public Oop getResolvedReferences() { - Address handle = resolvedReferences.getValue(getAddress()); - if (handle != null) { - // Load through the handle - OopHandle refs = handle.getOopHandleAt(0); - return VM.getVM().getObjectHeap().newOop(refs); - } - return null; + return getCache().getResolvedReferences(); + } + public KlassArray getResolvedKlasses() { + return new KlassArray(resolved_klasses.getValue(getAddress())); } public U2Array referenceMap() { - return new U2Array(referenceMap.getValue(getAddress())); + return getCache().referenceMap(); } public int objectToCPIndex(int index) { @@ -165,6 +165,16 @@ public class ConstantPool extends Metadata implements ClassConstants { return new CPSlot(getAddressAtRaw(index)); } + public CPKlassSlot getKlassSlotAt(long index) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(getTagAt(index).isUnresolvedKlass() || getTagAt(index).isKlass(), "Corrupted constant pool"); + } + int value = getIntAt(index); + int name_index = extractHighShortFromInt(value); + int resolved_klass_index = extractLowShortFromInt(value); + return new CPKlassSlot(name_index, resolved_klass_index); + } + public Address getAddressAtRaw(long index) { return getAddress().getAddressAt(indexOffset(index)); } @@ -315,16 +325,14 @@ public class ConstantPool extends Metadata implements ClassConstants { // returns null, if not resolved. public Klass getKlassAt(int which) { if( ! getTagAt(which).isKlass()) return null; - return (Klass)Metadata.instantiateWrapperFor(getAddressAtRaw(which)); + int resolved_klass_index = getKlassSlotAt(which).getResolvedKlassIndex(); + KlassArray resolved_klasses = getResolvedKlasses(); + return resolved_klasses.getAt(resolved_klass_index); } public Symbol getKlassNameAt(int which) { - CPSlot entry = getSlotAt(which); - if (entry.isResolved()) { - return entry.getKlass().getName(); - } else { - return entry.getSymbol(); - } + int name_index = getKlassSlotAt(which).getNameIndex(); + return getSymbolAt(name_index); } public Symbol getUnresolvedStringAt(int which) { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java index 3ac3ced3615..64fd3af0310 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPoolCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -51,6 +51,8 @@ public class ConstantPoolCache extends Metadata { elementSize = elType.getSize(); length = new CIntField(type.getCIntegerField("_length"), 0); intSize = VM.getVM().getObjectHeap().getIntSize(); + resolvedReferences = type.getAddressField("_resolved_references"); + referenceMap = type.getAddressField("_reference_map"); } public ConstantPoolCache(Address addr) { @@ -65,7 +67,8 @@ public class ConstantPoolCache extends Metadata { private static long elementSize; private static CIntField length; private static long intSize; - + private static AddressField resolvedReferences; + private static AddressField referenceMap; public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); } @@ -100,4 +103,18 @@ public class ConstantPoolCache extends Metadata { entry.iterateFields(visitor); } } + + public Oop getResolvedReferences() { + Address handle = resolvedReferences.getValue(getAddress()); + if (handle != null) { + // Load through the handle + OopHandle refs = handle.getOopHandleAt(0); + return VM.getVM().getObjectHeap().newOop(refs); + } + return null; + } + + public U2Array referenceMap() { + return new U2Array(referenceMap.getValue(getAddress())); + } }; diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index 742ec9a32e0..1456c019951 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -91,7 +91,6 @@ public class InstanceKlass extends Klass { fields = type.getAddressField("_fields"); javaFieldsCount = new CIntField(type.getCIntegerField("_java_fields_count"), 0); constants = new MetadataField(type.getAddressField("_constants"), 0); - classLoaderData = type.getAddressField("_class_loader_data"); sourceDebugExtension = type.getAddressField("_source_debug_extension"); innerClasses = type.getAddressField("_inner_classes"); sourceFileNameIndex = new CIntField(type.getCIntegerField("_source_file_name_index"), 0); @@ -166,7 +165,6 @@ public class InstanceKlass extends Klass { private static AddressField fields; private static CIntField javaFieldsCount; private static MetadataField constants; - private static AddressField classLoaderData; private static AddressField sourceDebugExtension; private static AddressField innerClasses; private static CIntField sourceFileNameIndex; @@ -328,7 +326,7 @@ public class InstanceKlass extends Klass { // MetaspaceObj in the CDS shared archive. Dictionary sharedDictionary = vm.getSystemDictionary().sharedDictionary(); if (sharedDictionary != null) { - if (sharedDictionary.contains(this, null)) { + if (sharedDictionary.contains(this)) { return true; } } @@ -448,8 +446,6 @@ public class InstanceKlass extends Klass { return allFieldsCount; } public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); } - public ClassLoaderData getClassLoaderData() { return ClassLoaderData.instantiateWrapperFor(classLoaderData.getValue(getAddress())); } - public Oop getClassLoader() { return getClassLoaderData().getClassLoader(); } public Symbol getSourceFileName() { return getConstants().getSymbolAt(sourceFileNameIndex.getValue(this)); } public String getSourceDebugExtension(){ return CStringUtilities.getString(sourceDebugExtension.getValue(getAddress())); } public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); } @@ -516,15 +512,7 @@ public class InstanceKlass extends Klass { if (ioff != 0) { // only look at classes that are already loaded // since we are looking for the flags for our self. - ConstantPool.CPSlot classInfo = getConstants().getSlotAt(ioff); - Symbol name = null; - if (classInfo.isResolved()) { - name = classInfo.getKlass().getName(); - } else if (classInfo.isUnresolved()) { - name = classInfo.getSymbol(); - } else { - throw new RuntimeException("should not reach here"); - } + Symbol name = getConstants().getKlassNameAt(ioff); if (name.equals(getName())) { // This is really a member class @@ -571,7 +559,6 @@ public class InstanceKlass extends Klass { // 'ioff' can be zero. // refer to JVM spec. section 4.7.5. if (ioff != 0) { - ConstantPool.CPSlot iclassInfo = getConstants().getSlotAt(ioff); Symbol innerName = getConstants().getKlassNameAt(ioff); Symbol myname = getName(); int ooff = innerClassList.at(i + @@ -592,15 +579,7 @@ public class InstanceKlass extends Klass { } } } else { - ConstantPool.CPSlot oclassInfo = getConstants().getSlotAt(ooff); - Symbol outerName = null; - if (oclassInfo.isResolved()) { - outerName = oclassInfo.getKlass().getName(); - } else if (oclassInfo.isUnresolved()) { - outerName = oclassInfo.getSymbol(); - } else { - throw new RuntimeException("should not reach here"); - } + Symbol outerName = getConstants().getKlassNameAt(ooff); // include only if current class is outer class. if (outerName.equals(myname) && innerName.equals(sym)) { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java index afa00274f1d..bc9431ca126 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/Klass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package sun.jvm.hotspot.oops; import java.io.*; import java.util.*; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.classfile.*; import sun.jvm.hotspot.runtime.*; import sun.jvm.hotspot.types.*; @@ -63,6 +64,7 @@ public class Klass extends Metadata implements ClassConstants { nextSibling = new MetadataField(type.getAddressField("_next_sibling"), 0); nextLink = new MetadataField(type.getAddressField("_next_link"), 0); vtableLen = new CIntField(type.getCIntegerField("_vtable_len"), 0); + classLoaderData = type.getAddressField("_class_loader_data"); LH_INSTANCE_SLOW_PATH_BIT = db.lookupIntConstant("Klass::_lh_instance_slow_path_bit").intValue(); LH_LOG2_ELEMENT_SIZE_SHIFT = db.lookupIntConstant("Klass::_lh_log2_element_size_shift").intValue(); @@ -96,6 +98,7 @@ public class Klass extends Metadata implements ClassConstants { private static MetadataField nextLink; private static sun.jvm.hotspot.types.Field traceIDField; private static CIntField vtableLen; + private static AddressField classLoaderData; private Address getValue(AddressField field) { return addr.getAddressAt(field.getOffset()); @@ -110,7 +113,7 @@ public class Klass extends Metadata implements ClassConstants { public Klass getSuper() { return (Klass) superField.getValue(this); } public Klass getJavaSuper() { return null; } public int getLayoutHelper() { return (int) layoutHelper.getValue(this); } - public Symbol getName() { return getSymbol(name); } + public Symbol getName() { return getSymbol(name); } public long getAccessFlags() { return accessFlags.getValue(this); } // Convenience routine public AccessFlags getAccessFlagsObj(){ return new AccessFlags(getAccessFlags()); } @@ -119,6 +122,9 @@ public class Klass extends Metadata implements ClassConstants { public Klass getNextLinkKlass() { return (Klass) nextLink.getValue(this); } public long getVtableLen() { return vtableLen.getValue(this); } + public ClassLoaderData getClassLoaderData() { return ClassLoaderData.instantiateWrapperFor(classLoaderData.getValue(getAddress())); } + public Oop getClassLoader() { return getClassLoaderData().getClassLoader(); } + public long traceID() { if (traceIDField == null) return 0; return traceIDField.getJLong(addr); diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java index 8a52e4efed4..3c986b8f6e1 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/OopUtilities.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2017, 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 @@ -59,20 +59,20 @@ public class OopUtilities { // parkBlocker field is new since 1.6 private static OopField threadParkBlockerField; + private static IntField threadPriorityField; + private static BooleanField threadDaemonField; + // possible values of java_lang_Thread::ThreadStatus private static int THREAD_STATUS_NEW; - /* - Other enum constants are not needed as of now. Uncomment these as and when needed. - private static int THREAD_STATUS_RUNNABLE; - private static int THREAD_STATUS_SLEEPING; - private static int THREAD_STATUS_IN_OBJECT_WAIT; - private static int THREAD_STATUS_IN_OBJECT_WAIT_TIMED; - private static int THREAD_STATUS_PARKED; - private static int THREAD_STATUS_PARKED_TIMED; - private static int THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER; - private static int THREAD_STATUS_TERMINATED; - */ + private static int THREAD_STATUS_RUNNABLE; + private static int THREAD_STATUS_SLEEPING; + private static int THREAD_STATUS_IN_OBJECT_WAIT; + private static int THREAD_STATUS_IN_OBJECT_WAIT_TIMED; + private static int THREAD_STATUS_PARKED; + private static int THREAD_STATUS_PARKED_TIMED; + private static int THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER; + private static int THREAD_STATUS_TERMINATED; // java.util.concurrent.locks.AbstractOwnableSynchronizer fields private static OopField absOwnSyncOwnerThreadField; @@ -229,20 +229,19 @@ public class OopUtilities { threadStatusField = (IntField) k.findField("threadStatus", "I"); threadParkBlockerField = (OopField) k.findField("parkBlocker", "Ljava/lang/Object;"); + threadPriorityField = (IntField) k.findField("priority", "I"); + threadDaemonField = (BooleanField) k.findField("daemon", "Z"); TypeDataBase db = VM.getVM().getTypeDataBase(); THREAD_STATUS_NEW = db.lookupIntConstant("java_lang_Thread::NEW").intValue(); - /* - Other enum constants are not needed as of now. Uncomment these as and when needed. - THREAD_STATUS_RUNNABLE = db.lookupIntConstant("java_lang_Thread::RUNNABLE").intValue(); - THREAD_STATUS_SLEEPING = db.lookupIntConstant("java_lang_Thread::SLEEPING").intValue(); - THREAD_STATUS_IN_OBJECT_WAIT = db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT").intValue(); - THREAD_STATUS_IN_OBJECT_WAIT_TIMED = db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT_TIMED").intValue(); - THREAD_STATUS_PARKED = db.lookupIntConstant("java_lang_Thread::PARKED").intValue(); - THREAD_STATUS_PARKED_TIMED = db.lookupIntConstant("java_lang_Thread::PARKED_TIMED").intValue(); - THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER = db.lookupIntConstant("java_lang_Thread::BLOCKED_ON_MONITOR_ENTER").intValue(); - THREAD_STATUS_TERMINATED = db.lookupIntConstant("java_lang_Thread::TERMINATED").intValue(); - */ + THREAD_STATUS_RUNNABLE = db.lookupIntConstant("java_lang_Thread::RUNNABLE").intValue(); + THREAD_STATUS_SLEEPING = db.lookupIntConstant("java_lang_Thread::SLEEPING").intValue(); + THREAD_STATUS_IN_OBJECT_WAIT = db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT").intValue(); + THREAD_STATUS_IN_OBJECT_WAIT_TIMED = db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT_TIMED").intValue(); + THREAD_STATUS_PARKED = db.lookupIntConstant("java_lang_Thread::PARKED").intValue(); + THREAD_STATUS_PARKED_TIMED = db.lookupIntConstant("java_lang_Thread::PARKED_TIMED").intValue(); + THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER = db.lookupIntConstant("java_lang_Thread::BLOCKED_ON_MONITOR_ENTER").intValue(); + THREAD_STATUS_TERMINATED = db.lookupIntConstant("java_lang_Thread::TERMINATED").intValue(); if (Assert.ASSERTS_ENABLED) { // it is okay to miss threadStatusField, because this was @@ -331,4 +330,46 @@ public class OopUtilities { return absOwnSyncOwnerThreadField.getValue(oop); } } + + public static int threadOopGetPriority(Oop threadOop) { + initThreadFields(); + if (threadPriorityField != null) { + return threadPriorityField.getValue(threadOop); + } else { + return 0; + } + } + + public static boolean threadOopGetDaemon(Oop threadOop) { + initThreadFields(); + if (threadDaemonField != null) { + return threadDaemonField.getValue(threadOop); + } else { + return false; + } + } + + public static String threadOopGetThreadStatusName(Oop threadOop) { + int status = OopUtilities.threadOopGetThreadStatus(threadOop); + if(status == THREAD_STATUS_NEW){ + return "NEW"; + }else if(status == THREAD_STATUS_RUNNABLE){ + return "RUNNABLE"; + }else if(status == THREAD_STATUS_SLEEPING){ + return "TIMED_WAITING (sleeping)"; + }else if(status == THREAD_STATUS_IN_OBJECT_WAIT){ + return "WAITING (on object monitor)"; + }else if(status == THREAD_STATUS_IN_OBJECT_WAIT_TIMED){ + return "TIMED_WAITING (on object monitor)"; + }else if(status == THREAD_STATUS_PARKED){ + return "WAITING (parking)"; + }else if(status == THREAD_STATUS_PARKED_TIMED){ + return "TIMED_WAITING (parking)"; + }else if(status == THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER){ + return "BLOCKED (on object monitor)"; + }else if(status == THREAD_STATUS_TERMINATED){ + return "TERMINATED"; + } + return "UNKNOWN"; + } } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java index 654948fba53..6932b0dee10 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java @@ -70,6 +70,8 @@ public class JavaThread extends Thread { private static int NOT_TERMINATED; private static int EXITING; + private static final String ADDRESS_FORMAT = VM.getVM().isLP64() ? "0x%016x" : "0x%08x"; + static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -475,4 +477,34 @@ public class JavaThread extends Thread { return access.getLastSP(addr); } + + public void printThreadInfoOn(PrintStream out){ + Oop threadOop = this.getThreadObj(); + + out.print("\""); + out.print(this.getThreadName()); + out.print("\" #"); + out.print(OopUtilities.threadOopGetTID(threadOop)); + if(OopUtilities.threadOopGetDaemon(threadOop)){ + out.print(" daemon"); + } + out.print(" prio="); + out.print(OopUtilities.threadOopGetPriority(threadOop)); + out.print(" tid="); + out.print(this.getAddress()); + out.print(" nid="); + out.print(String.format("0x%x ",this.getOSThread().threadId())); + out.print(getOSThread().getThreadState().getPrintVal()); + out.print(" ["); + if(this.getLastJavaSP() == null){ + out.print(String.format(ADDRESS_FORMAT,0L)); + } else { + out.print(this.getLastJavaSP().andWithMask(~0xFFF)); + } + out.println("]"); + out.print(" java.lang.Thread.State: "); + out.println(OopUtilities.threadOopGetThreadStatusName(threadOop)); + out.print(" JavaThread state: _thread_"); + out.println(this.getThreadState().toString().toLowerCase()); + } } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java index 226a1762570..978a87401d6 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/OSThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2017, 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 @@ -33,6 +33,19 @@ import sun.jvm.hotspot.types.*; public class OSThread extends VMObject { private static JIntField interruptedField; private static Field threadIdField; + private static CIntegerField threadStateField; + + // ThreadStates read from underlying process + private static int ALLOCATED; + private static int INITIALIZED; + private static int RUNNABLE; + private static int MONITOR_WAIT; + private static int CONDVAR_WAIT; + private static int OBJECT_WAIT; + private static int BREAKPOINTED; + private static int SLEEPING; + private static int ZOMBIE; + static { VM.registerVMInitializedObserver(new Observer() { public void update(Observable o, Object data) { @@ -45,6 +58,17 @@ public class OSThread extends VMObject { Type type = db.lookupType("OSThread"); interruptedField = type.getJIntField("_interrupted"); threadIdField = type.getField("_thread_id"); + threadStateField = type.getCIntegerField("_state"); + + ALLOCATED = db.lookupIntConstant("ALLOCATED").intValue(); + INITIALIZED = db.lookupIntConstant("INITIALIZED").intValue(); + RUNNABLE = db.lookupIntConstant("RUNNABLE").intValue(); + MONITOR_WAIT = db.lookupIntConstant("MONITOR_WAIT").intValue(); + CONDVAR_WAIT = db.lookupIntConstant("CONDVAR_WAIT").intValue(); + OBJECT_WAIT = db.lookupIntConstant("OBJECT_WAIT").intValue(); + BREAKPOINTED = db.lookupIntConstant("BREAKPOINTED").intValue(); + SLEEPING = db.lookupIntConstant("SLEEPING").intValue(); + ZOMBIE = db.lookupIntConstant("ZOMBIE").intValue(); } public OSThread(Address addr) { @@ -59,4 +83,28 @@ public class OSThread extends VMObject { return threadIdField.getJInt(addr); } + public ThreadState getThreadState() { + int val = (int)threadStateField.getValue(addr); + if (val == ALLOCATED) { + return ThreadState.ALLOCATED; + } else if (val == INITIALIZED) { + return ThreadState.INITIALIZED; + } else if (val == RUNNABLE) { + return ThreadState.RUNNABLE; + } else if (val == MONITOR_WAIT) { + return ThreadState.MONITOR_WAIT; + } else if (val == CONDVAR_WAIT) { + return ThreadState.CONDVAR_WAIT; + } else if (val == OBJECT_WAIT) { + return ThreadState.OBJECT_WAIT; + } else if (val == BREAKPOINTED) { + return ThreadState.BREAKPOINTED; + } else if (val == SLEEPING) { + return ThreadState.SLEEPING; + } else if (val == ZOMBIE) { + return ThreadState.ZOMBIE; + } else { + throw new RuntimeException("Illegal thread state " + val); + } + } } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java index 995b682754a..aee92a4f654 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ObjectSynchronizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2017, 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 @@ -108,13 +108,16 @@ public class ObjectSynchronizer { public Object next() { Address addr; - if (index > 0) { - addr = blockAddr.addOffsetTo(index*objectMonitorTypeSize); - } else { + if (index == 0) { + // advance to next block blockAddr = block.freeNext(); + if (blockAddr == null) { + throw new NoSuchElementException(); + } + block = new ObjectMonitor(blockAddr); index = blockSize - 1; - addr = blockAddr.addOffsetTo(index*objectMonitorTypeSize); } + addr = blockAddr.addOffsetTo(index*objectMonitorTypeSize); index --; return new ObjectMonitor(addr); } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadState.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadState.java new file mode 100644 index 00000000000..3538601dfbf --- /dev/null +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ThreadState.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.jvm.hotspot.runtime; + +/** This is a type-safe enum mirroring the ThreadState enum in + osThread.hpp. The conversion between the underlying ints + and these values is done in OSThread. */ + +public class ThreadState { + + private String printVal; + + /** Memory has been allocated but not initialized */ + public static final ThreadState ALLOCATED = new ThreadState("allocated"); + /** The thread has been initialized but yet started */ + public static final ThreadState INITIALIZED = new ThreadState("initialized"); + /** Has been started and is runnable, but not necessarily running */ + public static final ThreadState RUNNABLE = new ThreadState("runnable"); + /** Waiting on a contended monitor lock */ + public static final ThreadState MONITOR_WAIT = new ThreadState("waiting for monitor entry"); + /** Waiting on a condition variable */ + public static final ThreadState CONDVAR_WAIT = new ThreadState("waiting on condition"); + /** Waiting on an Object.wait() call */ + public static final ThreadState OBJECT_WAIT = new ThreadState("in Object.wait()"); + /** Suspended at breakpoint */ + public static final ThreadState BREAKPOINTED = new ThreadState("at breakpoint"); + /** Thread.sleep() */ + public static final ThreadState SLEEPING = new ThreadState("sleeping"); + /** All done, but not reclaimed yet */ + public static final ThreadState ZOMBIE = new ThreadState("zombie"); + + private ThreadState(String printVal){ + this.printVal = printVal; + } + + public String getPrintVal() { + return printVal; + } +} diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java index afa4660691f..65568fdd794 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/sparc/SPARCFrame.java @@ -845,7 +845,7 @@ public class SPARCFrame extends Frame { // // Also begin is one past last monitor. // // inline BasicObjectLock* frame::interpreter_frame_monitor_begin() const { - // int rounded_vm_local_words = round_to(frame::interpreter_frame_vm_local_words, WordsPerLong); + // int rounded_vm_local_words = align_up(frame::interpreter_frame_vm_local_words, WordsPerLong); // return (BasicObjectLock *)fp_addr_at(-rounded_vm_local_words); // } // @@ -860,7 +860,7 @@ public class SPARCFrame extends Frame { // // // inline int frame::interpreter_frame_monitor_size() { - // return round_to(BasicObjectLock::size(), WordsPerLong); + // return align_up(BasicObjectLock::size(), WordsPerLong); // } public Address addressOfInterpreterFrameMethod() { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java index 8dac3a84656..41b90f0a94e 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -28,6 +28,7 @@ import java.io.*; import java.util.*; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.classfile.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.runtime.*; @@ -106,8 +107,8 @@ public class ClassLoaderStats extends Tool { err.print("computing per loader stat .."); } - SystemDictionary dict = VM.getVM().getSystemDictionary(); - dict.classesDo(new SystemDictionary.ClassVisitor() { + ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph(); + cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() { public void visit(Klass k) { if (! (k instanceof InstanceKlass)) { return; diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java index c4e7b5c7b74..edf0b099b2a 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PStack.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ -88,6 +88,10 @@ public class PStack extends Tool { out.print("----------------- "); out.print(th); out.println(" -----------------"); + JavaThread jthread = (JavaThread) proxyToThread.get(th); + if (jthread != null) { + jthread.printThreadInfoOn(out); + } while (f != null) { ClosestSymbol sym = f.closestSymbolToPC(); Address pc = f.pc(); diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java index 6f519a74b14..7774fb68df0 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/StackTrace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -74,14 +74,7 @@ public class StackTrace extends Tool { int i = 1; for (JavaThread cur = threads.first(); cur != null; cur = cur.next(), i++) { if (cur.isJavaThread()) { - Address sp = cur.getLastJavaSP(); - tty.print("Thread "); - cur.printThreadIDOn(tty); - tty.print(": (state = " + cur.getThreadState()); - if (verbose) { - tty.println(", current Java SP = " + sp); - } - tty.println(')'); + cur.printThreadInfoOn(tty); try { for (JavaVFrame vf = cur.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) { Method method = vf.getMethod(); diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java index 98300c1d6c4..e47816a5c66 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ClassDump.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -29,6 +29,7 @@ import java.lang.reflect.Constructor; import java.util.jar.JarOutputStream; import java.util.jar.JarEntry; import java.util.jar.Manifest; +import sun.jvm.hotspot.classfile.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.debugger.*; @@ -100,9 +101,9 @@ public class ClassDump extends Tool { setOutputDirectory(dirName); } - // walk through the system dictionary - SystemDictionary dict = VM.getVM().getSystemDictionary(); - dict.classesDo(new SystemDictionary.ClassVisitor() { + // walk through the loaded classes + ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph(); + cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() { public void visit(Klass k) { if (k instanceof InstanceKlass) { try { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java index a5c811b8280..17d24d4f145 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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 @@ -630,11 +630,12 @@ public class HTMLGenerator implements /* imports */ ClassConstants { buf.beginTag("ul"); for (int exp = 0; exp < exceptions.length; exp++) { short cpIndex = (short) exceptions[exp].getClassCPIndex(); - ConstantPool.CPSlot obj = cpool.getSlotAt(cpIndex); - if (obj.isUnresolved()) { - buf.li((obj.getSymbol()).asString().replace('/', '.')); + ConstantTag tag = cpool.getTagAt(cpIndex); + if (tag.isUnresolvedKlass()) { + buf.li(cpool.getKlassNameAt(cpIndex).asString().replace('/', '.')); } else { - buf.li(genKlassLink((InstanceKlass)obj.getKlass())); + Klass k = cpool.getKlassAt(cpIndex); + buf.li(genKlassLink((InstanceKlass)k)); } } buf.endTag("ul"); @@ -766,13 +767,14 @@ public class HTMLGenerator implements /* imports */ ClassConstants { buf.cell(Integer.toString(exceptionTable[e].getEndPC())); buf.cell(Integer.toString(exceptionTable[e].getHandlerPC())); short cpIndex = (short) exceptionTable[e].getCatchTypeIndex(); - ConstantPool.CPSlot obj = cpIndex == 0? null : cpool.getSlotAt(cpIndex); - if (obj == null) { - buf.cell("Any"); - } else if (obj.isUnresolved()) { - buf.cell(obj.getSymbol().asString().replace('/', '.')); + ConstantTag tag = cpIndex == 0? null : cpool.getTagAt(cpIndex); + if (tag == null) { + buf.cell("Any"); + } else if (tag.isUnresolvedKlass()) { + buf.cell(cpool.getKlassNameAt(cpIndex).asString().replace('/', '.')); } else { - buf.cell(genKlassLink((InstanceKlass)obj.getKlass())); + Klass k = cpool.getKlassAt(cpIndex); + buf.cell(genKlassLink((InstanceKlass)k)); } buf.endTag("tr"); } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/GenericArray.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/GenericArray.java index fa13cab041e..fc1c4341e8c 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/GenericArray.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/GenericArray.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + package sun.jvm.hotspot.utilities; import java.util.Observable; diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/Hashtable.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/Hashtable.java index ea4fa581a8e..b69afb78682 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/Hashtable.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/Hashtable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package sun.jvm.hotspot.utilities; import java.util.*; import sun.jvm.hotspot.debugger.*; import sun.jvm.hotspot.types.*; +import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.runtime.*; public class Hashtable extends BasicHashtable { @@ -48,6 +49,10 @@ public class Hashtable extends BasicHashtable { return HashtableEntry.class; } + public int computeHash(Symbol name) { + return (int) name.identityHash(); + } + public int hashToIndex(long fullHash) { return (int) (fullHash % tableSize()); } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java index c9e3c122310..d329fa441c3 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java @@ -586,23 +586,9 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter { } private void writeClassDumpRecords() throws IOException { - SystemDictionary sysDict = VM.getVM().getSystemDictionary(); ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph(); try { - sysDict.allClassesDo(new SystemDictionary.ClassVisitor() { - public void visit(Klass k) { - try { - writeHeapRecordPrologue(); - writeClassDumpRecord(k); - writeHeapRecordEpilogue(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }); - // Add the anonymous classes also which are not present in the - // System Dictionary - cldGraph.allAnonymousKlassesDo(new ClassLoaderDataGraph.KlassVisitor() { + cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() { public void visit(Klass k) { try { writeHeapRecordPrologue(); @@ -1088,26 +1074,9 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter { private void writeClasses() throws IOException { // write class list (id, name) association - SystemDictionary sysDict = VM.getVM().getSystemDictionary(); ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph(); try { - sysDict.allClassesDo(new SystemDictionary.ClassVisitor() { - public void visit(Klass k) { - try { - Instance clazz = k.getJavaMirror(); - writeHeader(HPROF_LOAD_CLASS, 2 * (OBJ_ID_SIZE + 4)); - out.writeInt(serialNum); - writeObjectID(clazz); - KlassMap.add(serialNum - 1, k); - out.writeInt(DUMMY_STACK_TRACE_ID); - writeSymbolID(k.getName()); - serialNum++; - } catch (IOException exp) { - throw new RuntimeException(exp); - } - } - }); - cldGraph.allAnonymousKlassesDo(new ClassLoaderDataGraph.KlassVisitor() { + cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() { public void visit(Klass k) { try { Instance clazz = k.getJavaMirror(); diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/IntArray.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/IntArray.java index 09cf93cd78c..5737c5f668f 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/IntArray.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/IntArray.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + package sun.jvm.hotspot.utilities; import java.util.Observable; diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java index 50a8d4d62a8..2f4cb23c98c 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ReversePtrsAnalysis.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package sun.jvm.hotspot.utilities; import java.io.*; import java.util.*; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.classfile.*; import sun.jvm.hotspot.gc.shared.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.oops.*; @@ -113,8 +114,8 @@ public class ReversePtrsAnalysis { new RootVisitor("Weak global JNI handle root")); // Do Java-level static fields - SystemDictionary sysDict = VM.getVM().getSystemDictionary(); - sysDict.allClassesDo(new SystemDictionary.ClassVisitor() { + ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph(); + cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() { public void visit(Klass k) { if (k instanceof InstanceKlass) { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/SystemDictionaryHelper.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/SystemDictionaryHelper.java index f1364da4610..d69a54ac4ef 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/SystemDictionaryHelper.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/SystemDictionaryHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2017, 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,6 +25,7 @@ package sun.jvm.hotspot.utilities; import java.util.*; +import sun.jvm.hotspot.classfile.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.runtime.*; @@ -52,8 +53,8 @@ public class SystemDictionaryHelper { } final Vector tmp = new Vector(); - SystemDictionary dict = VM.getVM().getSystemDictionary(); - dict.classesDo(new SystemDictionary.ClassVisitor() { + ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph(); + cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() { public void visit(Klass k) { if (k instanceof InstanceKlass) { InstanceKlass ik = (InstanceKlass) k; @@ -100,42 +101,15 @@ public class SystemDictionaryHelper { public static InstanceKlass findInstanceKlass(String className) { // convert to internal name className = className.replace('.', '/'); - SystemDictionary sysDict = VM.getVM().getSystemDictionary(); + ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph(); - // check whether we have a bootstrap class of given name - Klass klass = sysDict.find(className, null, null); - if (klass != null) { + // check whether we have a class of given name + Klass klass = cldg.find(className); + if (klass != null && klass instanceof InstanceKlass) { return (InstanceKlass) klass; + } else { + // no match .. + return null; } - - // check whether we have a system class of given name - klass = sysDict.find(className, sysDict.javaSystemLoader(), null); - if (klass != null) { - return (InstanceKlass) klass; - } - - // didn't find bootstrap or system class of given name. - // search through the entire dictionary.. - InstanceKlass[] tmpKlasses = getAllInstanceKlasses(); - // instance klass array is sorted by name. do binary search - int low = 0; - int high = tmpKlasses.length-1; - - int mid = -1; - while (low <= high) { - mid = (low + high) >> 1; - InstanceKlass midVal = tmpKlasses[mid]; - int cmp = midVal.getName().asString().compareTo(className); - - if (cmp < 0) { - low = mid + 1; - } else if (cmp > 0) { - high = mid - 1; - } else { // match found - return tmpKlasses[mid]; - } - } - // no match .. - return null; } } diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaHeap.java b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaHeap.java index 87e6688889f..053ddbce4b4 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaHeap.java +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/JSJavaHeap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package sun.jvm.hotspot.utilities.soql; import java.util.*; import javax.script.ScriptException; import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.classfile.*; import sun.jvm.hotspot.memory.*; import sun.jvm.hotspot.oops.*; import sun.jvm.hotspot.runtime.*; @@ -166,11 +167,12 @@ public class JSJavaHeap extends DefaultScriptObject { } final Callable finalFunc = func; - SystemDictionary sysDict = VM.getVM().getSystemDictionary(); + ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph(); if (withLoader) { - sysDict.classesDo(new SystemDictionary.ClassAndLoaderVisitor() { - public void visit(Klass kls, Oop loader) { + cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() { + public void visit(Klass kls) { JSJavaKlass jk = factory.newJSJavaKlass(kls); + Oop loader = kls.getClassLoader(); if (jk == null) { return; } @@ -189,7 +191,7 @@ public class JSJavaHeap extends DefaultScriptObject { }); } else { - sysDict.classesDo(new SystemDictionary.ClassVisitor() { + cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() { public void visit(Klass kls) { JSJavaKlass jk = factory.newJSJavaKlass(kls); if (jk == null) { diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js index 2bd5c556d0d..a011c32639c 100644 --- a/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js +++ b/hotspot/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/soql/sa.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2017, 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 @@ -513,24 +513,18 @@ function systemLoader() { return sa.sysDict.javaSystemLoader(); } -// iterate system dictionary for each 'Klass' +// iterate class loader data for each 'Klass' function forEachKlass(callback) { - var VisitorClass = sapkg.memory.SystemDictionary.ClassVisitor; + var VisitorClass = sapkg.classfile.ClassLoaderDataGraph.ClassVisitor; var visitor = new VisitorClass() { visit: callback }; - sa.sysDict["classesDo(sun.jvm.hotspot.memory.SystemDictionary.ClassVisitor)"](visitor); + sa.sysDict["classesDo(sun.jvm.hotspot.classfile.ClassLoaderDataGraph.ClassVisitor)"](visitor); } // iterate system dictionary for each 'Klass' and initiating loader function forEachKlassAndLoader(callback) { - var VisitorClass = sapkg.memory.SystemDictionary.ClassAndLoaderVisitor; + var VisitorClass = sapkg.classfile.ClassLoaderDataGraph.ClassAndLoaderVisitor; var visitor = new VisitorClass() { visit: callback }; - sa.sysDict["classesDo(sun.jvm.hotspot.memory.SystemDictionary.ClassAndLoaderVisitor)"](visitor); -} - -// iterate system dictionary for each primitive array klass -function forEachPrimArrayKlass(callback) { - var VisitorClass = sapkg.memory.SystemDictionary.ClassAndLoaderVisitor; - sa.sysDict.primArrayClassesDo(new VisitorClass() { visit: callback }); + sa.sysDict["allEntriesDo(sun.jvm.hotspot.classfile.ClassLoaderDataGraph.ClassAndLoaderVisitor)"](visitor); } // 'oop' to higher-level java object wrapper in which for(i in o) diff --git a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java index d2fb255e721..7006517548f 100644 --- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java +++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotJVMCIBackendFactory.java @@ -57,72 +57,120 @@ public class SPARCHotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto protected EnumSet computeFeatures(SPARCHotSpotVMConfig config) { EnumSet features = EnumSet.noneOf(CPUFeature.class); - if ((config.vmVersionFeatures & config.sparcVis1Instructions) != 0) { - features.add(CPUFeature.VIS1); + + if ((config.vmVersionFeatures & 1L << config.sparc_ADI) != 0) { + features.add(CPUFeature.ADI); } - if ((config.vmVersionFeatures & config.sparcVis2Instructions) != 0) { - features.add(CPUFeature.VIS2); + if ((config.vmVersionFeatures & 1L << config.sparc_AES) != 0) { + features.add(CPUFeature.AES); } - if ((config.vmVersionFeatures & config.sparcVis3Instructions) != 0) { - features.add(CPUFeature.VIS3); + if ((config.vmVersionFeatures & 1L << config.sparc_BLK_INIT) != 0) { + features.add(CPUFeature.BLK_INIT); } - if ((config.vmVersionFeatures & config.sparcCbcondInstructions) != 0) { + if ((config.vmVersionFeatures & 1L << config.sparc_CAMELLIA) != 0) { + features.add(CPUFeature.CAMELLIA); + } + if ((config.vmVersionFeatures & 1L << config.sparc_CBCOND) != 0) { features.add(CPUFeature.CBCOND); } - if ((config.vmVersionFeatures & config.sparcV8Instructions) != 0) { - features.add(CPUFeature.V8); + if ((config.vmVersionFeatures & 1L << config.sparc_CRC32C) != 0) { + features.add(CPUFeature.CRC32C); } - if ((config.vmVersionFeatures & config.sparcHardwareMul32) != 0) { - features.add(CPUFeature.HARDWARE_MUL32); + if ((config.vmVersionFeatures & 1L << config.sparc_DES) != 0) { + features.add(CPUFeature.DES); } - if ((config.vmVersionFeatures & config.sparcHardwareDiv32) != 0) { - features.add(CPUFeature.HARDWARE_DIV32); - } - if ((config.vmVersionFeatures & config.sparcHardwareFsmuld) != 0) { - features.add(CPUFeature.HARDWARE_FSMULD); - } - if ((config.vmVersionFeatures & config.sparcHardwarePopc) != 0) { - features.add(CPUFeature.HARDWARE_POPC); - } - if ((config.vmVersionFeatures & config.sparcV9Instructions) != 0) { - features.add(CPUFeature.V9); - } - if ((config.vmVersionFeatures & config.sparcSun4v) != 0) { - features.add(CPUFeature.SUN4V); - } - if ((config.vmVersionFeatures & config.sparcBlkInitInstructions) != 0) { - features.add(CPUFeature.BLK_INIT_INSTRUCTIONS); - } - if ((config.vmVersionFeatures & config.sparcFmafInstructions) != 0) { + if ((config.vmVersionFeatures & 1L << config.sparc_FMAF) != 0) { features.add(CPUFeature.FMAF); } - if ((config.vmVersionFeatures & config.sparcSparc64Family) != 0) { - features.add(CPUFeature.SPARC64_FAMILY); + if ((config.vmVersionFeatures & 1L << config.sparc_HPC) != 0) { + features.add(CPUFeature.HPC); } - if ((config.vmVersionFeatures & config.sparcMFamily) != 0) { - features.add(CPUFeature.M_FAMILY); + if ((config.vmVersionFeatures & 1L << config.sparc_IMA) != 0) { + features.add(CPUFeature.IMA); } - if ((config.vmVersionFeatures & config.sparcTFamily) != 0) { - features.add(CPUFeature.T_FAMILY); + if ((config.vmVersionFeatures & 1L << config.sparc_KASUMI) != 0) { + features.add(CPUFeature.KASUMI); } - if ((config.vmVersionFeatures & config.sparcT1Model) != 0) { - features.add(CPUFeature.T1_MODEL); + if ((config.vmVersionFeatures & 1L << config.sparc_MD5) != 0) { + features.add(CPUFeature.MD5); } - if ((config.vmVersionFeatures & config.sparcSparc5Instructions) != 0) { - features.add(CPUFeature.SPARC5); + if ((config.vmVersionFeatures & 1L << config.sparc_MONT) != 0) { + features.add(CPUFeature.MONT); } - if ((config.vmVersionFeatures & config.sparcAesInstructions) != 0) { - features.add(CPUFeature.SPARC64_FAMILY); + if ((config.vmVersionFeatures & 1L << config.sparc_MPMUL) != 0) { + features.add(CPUFeature.MPMUL); } - if ((config.vmVersionFeatures & config.sparcSha1Instruction) != 0) { + if ((config.vmVersionFeatures & 1L << config.sparc_MWAIT) != 0) { + features.add(CPUFeature.MWAIT); + } + if ((config.vmVersionFeatures & 1L << config.sparc_PAUSE) != 0) { + features.add(CPUFeature.PAUSE); + } + if ((config.vmVersionFeatures & 1L << config.sparc_PAUSE_NSEC) != 0) { + features.add(CPUFeature.PAUSE_NSEC); + } + if ((config.vmVersionFeatures & 1L << config.sparc_POPC) != 0) { + features.add(CPUFeature.POPC); + } + if ((config.vmVersionFeatures & 1L << config.sparc_SHA1) != 0) { features.add(CPUFeature.SHA1); } - if ((config.vmVersionFeatures & config.sparcSha256Instruction) != 0) { + if ((config.vmVersionFeatures & 1L << config.sparc_SHA256) != 0) { features.add(CPUFeature.SHA256); } - if ((config.vmVersionFeatures & config.sparcSha512Instruction) != 0) { + if ((config.vmVersionFeatures & 1L << config.sparc_SHA512) != 0) { features.add(CPUFeature.SHA512); } + if ((config.vmVersionFeatures & 1L << config.sparc_SPARC5) != 0) { + features.add(CPUFeature.SPARC5); + } + if ((config.vmVersionFeatures & 1L << config.sparc_V9) != 0) { + features.add(CPUFeature.V9); + } + if ((config.vmVersionFeatures & 1L << config.sparc_VAMASK) != 0) { + features.add(CPUFeature.VAMASK); + } + if ((config.vmVersionFeatures & 1L << config.sparc_VIS1) != 0) { + features.add(CPUFeature.VIS1); + } + if ((config.vmVersionFeatures & 1L << config.sparc_VIS2) != 0) { + features.add(CPUFeature.VIS2); + } + if ((config.vmVersionFeatures & 1L << config.sparc_VIS3) != 0) { + features.add(CPUFeature.VIS3); + } + if ((config.vmVersionFeatures & 1L << config.sparc_VIS3B) != 0) { + features.add(CPUFeature.VIS3B); + } + if ((config.vmVersionFeatures & 1L << config.sparc_XMONT) != 0) { + features.add(CPUFeature.XMONT); + } + if ((config.vmVersionFeatures & 1L << config.sparc_XMPMUL) != 0) { + features.add(CPUFeature.XMPMUL); + } + + if ((config.vmVersionFeatures & 1L << config.sparc_BLK_ZEROING) != 0) { + features.add(CPUFeature.BLK_ZEROING); + } + if ((config.vmVersionFeatures & 1L << config.sparc_FAST_BIS) != 0) { + features.add(CPUFeature.FAST_BIS); + } + if ((config.vmVersionFeatures & 1L << config.sparc_FAST_CMOVE) != 0) { + features.add(CPUFeature.FAST_CMOVE); + } + if ((config.vmVersionFeatures & 1L << config.sparc_FAST_IDIV) != 0) { + features.add(CPUFeature.FAST_IDIV); + } + if ((config.vmVersionFeatures & 1L << config.sparc_FAST_IND_BR) != 0) { + features.add(CPUFeature.FAST_IND_BR); + } + if ((config.vmVersionFeatures & 1L << config.sparc_FAST_LD) != 0) { + features.add(CPUFeature.FAST_LD); + } + if ((config.vmVersionFeatures & 1L << config.sparc_FAST_RDPC) != 0) { + features.add(CPUFeature.FAST_RDPC); + } + return features; } diff --git a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotVMConfig.java b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotVMConfig.java index f0b1591554a..a5ae1d85eef 100644 --- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotVMConfig.java +++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot.sparc/src/jdk/vm/ci/hotspot/sparc/SPARCHotSpotVMConfig.java @@ -38,32 +38,54 @@ class SPARCHotSpotVMConfig extends HotSpotVMConfigAccess { final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class); - // CPU capabilities + // CPU capabilities: + // + // FIXME: Using a 64-bit value is insufficient to support future capability + // sets (including co-processor capabilities such as DAX). final long vmVersionFeatures = getFieldValue("Abstract_VM_Version::_features", Long.class, "uint64_t"); - // SPARC specific values - final int sparcVis3Instructions = getConstant("VM_Version::vis3_instructions_m", Integer.class); - final int sparcVis2Instructions = getConstant("VM_Version::vis2_instructions_m", Integer.class); - final int sparcVis1Instructions = getConstant("VM_Version::vis1_instructions_m", Integer.class); - final int sparcCbcondInstructions = getConstant("VM_Version::cbcond_instructions_m", Integer.class); - final int sparcV8Instructions = getConstant("VM_Version::v8_instructions_m", Integer.class); - final int sparcHardwareMul32 = getConstant("VM_Version::hardware_mul32_m", Integer.class); - final int sparcHardwareDiv32 = getConstant("VM_Version::hardware_div32_m", Integer.class); - final int sparcHardwareFsmuld = getConstant("VM_Version::hardware_fsmuld_m", Integer.class); - final int sparcHardwarePopc = getConstant("VM_Version::hardware_popc_m", Integer.class); - final int sparcV9Instructions = getConstant("VM_Version::v9_instructions_m", Integer.class); - final int sparcSun4v = getConstant("VM_Version::sun4v_m", Integer.class); - final int sparcBlkInitInstructions = getConstant("VM_Version::blk_init_instructions_m", Integer.class); - final int sparcFmafInstructions = getConstant("VM_Version::fmaf_instructions_m", Integer.class); - final int sparcSparc64Family = getConstant("VM_Version::sparc64_family_m", Integer.class); - final int sparcMFamily = getConstant("VM_Version::M_family_m", Integer.class); - final int sparcTFamily = getConstant("VM_Version::T_family_m", Integer.class); - final int sparcT1Model = getConstant("VM_Version::T1_model_m", Integer.class); - final int sparcSparc5Instructions = getConstant("VM_Version::sparc5_instructions_m", Integer.class); - final int sparcAesInstructions = getConstant("VM_Version::aes_instructions_m", Integer.class); - final int sparcSha1Instruction = getConstant("VM_Version::sha1_instruction_m", Integer.class); - final int sparcSha256Instruction = getConstant("VM_Version::sha256_instruction_m", Integer.class); - final int sparcSha512Instruction = getConstant("VM_Version::sha512_instruction_m", Integer.class); + // SPARC specific values: + // + // NOTE: Values changed into an enumeration (that do indeed fit within a + // 32-bit integer) instead of the exported (64-bit wide) bit-masks. + final int sparc_ADI = getConstant("VM_Version::ISA_ADI", Integer.class); + final int sparc_AES = getConstant("VM_Version::ISA_AES", Integer.class); + final int sparc_BLK_INIT = getConstant("VM_Version::ISA_BLK_INIT", Integer.class); + final int sparc_CAMELLIA = getConstant("VM_Version::ISA_CAMELLIA", Integer.class); + final int sparc_CBCOND = getConstant("VM_Version::ISA_CBCOND", Integer.class); + final int sparc_CRC32C = getConstant("VM_Version::ISA_CRC32C", Integer.class); + final int sparc_DES = getConstant("VM_Version::ISA_DES", Integer.class); + final int sparc_FMAF = getConstant("VM_Version::ISA_FMAF", Integer.class); + final int sparc_HPC = getConstant("VM_Version::ISA_HPC", Integer.class); + final int sparc_IMA = getConstant("VM_Version::ISA_IMA", Integer.class); + final int sparc_KASUMI = getConstant("VM_Version::ISA_KASUMI", Integer.class); + final int sparc_MD5 = getConstant("VM_Version::ISA_MD5", Integer.class); + final int sparc_MONT = getConstant("VM_Version::ISA_MONT", Integer.class); + final int sparc_MPMUL = getConstant("VM_Version::ISA_MPMUL", Integer.class); + final int sparc_MWAIT = getConstant("VM_Version::ISA_MWAIT", Integer.class); + final int sparc_PAUSE = getConstant("VM_Version::ISA_PAUSE", Integer.class); + final int sparc_PAUSE_NSEC = getConstant("VM_Version::ISA_PAUSE_NSEC", Integer.class); + final int sparc_POPC = getConstant("VM_Version::ISA_POPC", Integer.class); + final int sparc_SHA1 = getConstant("VM_Version::ISA_SHA1", Integer.class); + final int sparc_SHA256 = getConstant("VM_Version::ISA_SHA256", Integer.class); + final int sparc_SHA512 = getConstant("VM_Version::ISA_SHA512", Integer.class); + final int sparc_SPARC5 = getConstant("VM_Version::ISA_SPARC5", Integer.class); + final int sparc_V9 = getConstant("VM_Version::ISA_V9", Integer.class); + final int sparc_VAMASK = getConstant("VM_Version::ISA_VAMASK", Integer.class); + final int sparc_VIS1 = getConstant("VM_Version::ISA_VIS1", Integer.class); + final int sparc_VIS2 = getConstant("VM_Version::ISA_VIS2", Integer.class); + final int sparc_VIS3 = getConstant("VM_Version::ISA_VIS3", Integer.class); + final int sparc_VIS3B = getConstant("VM_Version::ISA_VIS3B", Integer.class); + final int sparc_XMONT = getConstant("VM_Version::ISA_XMONT", Integer.class); + final int sparc_XMPMUL = getConstant("VM_Version::ISA_XMPMUL", Integer.class); + + final int sparc_BLK_ZEROING = getConstant("VM_Version::CPU_BLK_ZEROING", Integer.class); + final int sparc_FAST_BIS = getConstant("VM_Version::CPU_FAST_BIS", Integer.class); + final int sparc_FAST_CMOVE = getConstant("VM_Version::CPU_FAST_CMOVE", Integer.class); + final int sparc_FAST_IDIV = getConstant("VM_Version::CPU_FAST_IDIV", Integer.class); + final int sparc_FAST_IND_BR = getConstant("VM_Version::CPU_FAST_IND_BR", Integer.class); + final int sparc_FAST_LD = getConstant("VM_Version::CPU_FAST_LD", Integer.class); + final int sparc_FAST_RDPC = getConstant("VM_Version::CPU_FAST_RDPC", Integer.class); final boolean useBlockZeroing = getFlag("UseBlockZeroing", Boolean.class); final int blockZeroingLowLimit = getFlag("BlockZeroingLowLimit", Integer.class); diff --git a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java index 450c1dfc4dd..2516a79f743 100644 --- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java @@ -459,9 +459,9 @@ final class CompilerToVM { native long getLocalVariableTableStart(HotSpotResolvedJavaMethodImpl method); /** - * Determines if {@code method} should not be inlined or compiled. + * Sets flags on {@code method} indicating that it should never be inlined or compiled by the VM. */ - native void doNotInlineOrCompile(HotSpotResolvedJavaMethodImpl method); + native void setNotInlineableOrCompileable(HotSpotResolvedJavaMethodImpl method); /** * Invalidates the profiling information for {@code method} and (re)initializes it such that diff --git a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java index c6dd6f2410b..60ae8f4a764 100644 --- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java +++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2017, 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 @@ -52,7 +52,8 @@ public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProv static final ResolvedJavaType lambdaFormType; static final ResolvedJavaField methodHandleFormField; static final ResolvedJavaField lambdaFormVmentryField; - static final HotSpotResolvedJavaField memberNameVmtargetField; + static final ResolvedJavaField methodField; + static final HotSpotResolvedJavaField vmtargetField; /** * Search for an instance field with the given name in a class. @@ -88,7 +89,10 @@ public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProv lambdaFormType = resolveType("java.lang.invoke.LambdaForm"); methodHandleFormField = findFieldInClass(methodHandleType, "form", lambdaFormType); lambdaFormVmentryField = findFieldInClass(lambdaFormType, "vmentry", memberNameType); - memberNameVmtargetField = (HotSpotResolvedJavaField) findFieldInClass(memberNameType, "vmtarget", resolveType(long.class)); + ResolvedJavaType methodType = resolveType("java.lang.invoke.ResolvedMethodName"); + methodField = findFieldInClass(memberNameType, "method", methodType); + vmtargetField = (HotSpotResolvedJavaField) findFieldInClass(methodType, "vmtarget", resolveType(HotSpotJVMCIRuntime.getHostWordKind().toJavaClass())); + } catch (Throwable ex) { throw new JVMCIError(ex); } @@ -139,24 +143,30 @@ public class HotSpotMethodHandleAccessProvider implements MethodHandleAccessProv memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm); assert memberName.isNonNull(); } - return getTargetMethod(memberName); + JavaConstant method = constantReflection.readFieldValue(LazyInitialization.methodField, memberName); + return getTargetMethod(method); } @Override public ResolvedJavaMethod resolveLinkToTarget(JavaConstant memberName) { - return getTargetMethod(memberName); - } - - /** - * Returns the {@link ResolvedJavaMethod} for the vmtarget of a java.lang.invoke.MemberName. - */ - private static ResolvedJavaMethod getTargetMethod(JavaConstant memberName) { if (memberName.isNull()) { return null; } + JavaConstant method = constantReflection.readFieldValue(LazyInitialization.methodField, memberName); + return getTargetMethod(method); + } - Object object = ((HotSpotObjectConstantImpl) memberName).object(); - /* Read the ResolvedJavaMethod from the injected field MemberName.vmtarget */ - return compilerToVM().getResolvedJavaMethod(object, LazyInitialization.memberNameVmtargetField.offset()); + /** + * Returns the {@link ResolvedJavaMethod} for the method of a java.lang.invoke.MemberName. + */ + private static ResolvedJavaMethod getTargetMethod(JavaConstant method) { + if (method == null) { + // If readFieldValue returns NULL the type was wrong + throw new IllegalArgumentException("unexpected type for memberName"); + } + + Object object = ((HotSpotObjectConstantImpl) method).object(); + /* Read the ResolvedJavaMethod from the injected field MemberName.method.vmtarget */ + return compilerToVM().getResolvedJavaMethod(object, LazyInitialization.vmtargetField.offset()); } } diff --git a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java index af75f81a2ff..5a71dd513de 100644 --- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java +++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethod.java @@ -57,9 +57,9 @@ public interface HotSpotResolvedJavaMethod extends ResolvedJavaMethod { boolean hasReservedStackAccess(); /** - * Manually adds a DontInline annotation to this method. + * Sets flags on {@code method} indicating that it should never be inlined or compiled by the VM. */ - void setNotInlineable(); + void setNotInlineableOrCompileable(); /** * Returns true if this method is one of the special methods that is ignored by security stack diff --git a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index f831db4c5f9..51b556ae038 100644 --- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -318,10 +318,10 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp } /** - * Manually adds a DontInline annotation to this method. + * Sets flags on {@code method} indicating that it should never be inlined or compiled by the VM. */ - public void setNotInlineable() { - compilerToVM().doNotInlineOrCompile(this); + public void setNotInlineableOrCompileable() { + compilerToVM().setNotInlineableOrCompileable(this); } /** diff --git a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java index 989c719144b..9df6c20e8c6 100644 --- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java +++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java @@ -39,7 +39,7 @@ public class HotSpotSpeculationLog implements SpeculationLog { private Set failedSpeculations; /** Strong references to all reasons embedded in the current nmethod. */ - private volatile Collection speculations; + private Collection speculations; @Override public synchronized void collectFailedSpeculations() { @@ -70,14 +70,12 @@ public class HotSpotSpeculationLog implements SpeculationLog { * reason objects that are embedded in nmethods, so we add them to the speculations * collection. */ - if (speculations == null) { - synchronized (this) { - if (speculations == null) { - speculations = new ConcurrentLinkedQueue<>(); - } + synchronized (this) { + if (speculations == null) { + speculations = new ConcurrentLinkedQueue<>(); } + speculations.add(reason); } - speculations.add(reason); return HotSpotObjectConstantImpl.forObject(reason); } diff --git a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java index eb3d78e2933..ee40d426346 100644 --- a/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java +++ b/hotspot/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.sparc/src/jdk/vm/ci/sparc/SPARC.java @@ -336,27 +336,44 @@ public class SPARC extends Architecture { } public enum CPUFeature { + // ISA determined properties: + ADI, + AES, + BLK_INIT, + CAMELLIA, + CBCOND, + CRC32C, + DES, + FMAF, + HPC, + IMA, + KASUMI, + MD5, + MONT, + MPMUL, + MWAIT, + PAUSE, + PAUSE_NSEC, + POPC, + SHA1, + SHA256, + SHA512, + SPARC5, + V9, + VAMASK, VIS1, VIS2, VIS3, - CBCOND, - V8, - HARDWARE_MUL32, - HARDWARE_DIV32, - HARDWARE_FSMULD, - HARDWARE_POPC, - V9, - SUN4V, - BLK_INIT_INSTRUCTIONS, - FMAF, - SPARC64_FAMILY, - M_FAMILY, - T_FAMILY, - T1_MODEL, - SPARC5, - AES, - SHA1, - SHA256, - SHA512 + VIS3B, + XMONT, + XMPMUL, + // Synthesised CPU properties: + BLK_ZEROING, + FAST_BIS, + FAST_CMOVE, + FAST_IDIV, + FAST_IND_BR, + FAST_LD, + FAST_RDPC } } diff --git a/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py b/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py index b7f897c0862..6dd8b072ee2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py +++ b/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py @@ -47,6 +47,7 @@ suite = { "sha1" : "476d9a44cd19d6b55f81571077dfa972a4f8a083", "bootClassPathAgent" : "true", }, + "ASM5" : { "sha1" : "0da08b8cce7bbf903602a25a3a163ae252435795", "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/asm-5.0.4.jar"], @@ -60,15 +61,29 @@ suite = { }, "projects" : { - - # ------------- Graal ------------- - "org.graalvm.compiler.common" : { + # -------------- SDK -------------- + "org.graalvm.options" : { "subDir" : "share/classes", "sourceDirs" : ["src"], - "checkstyle" : "org.graalvm.compiler.graph", + "dependencies" : [], + "uses" : [], + "exports" : [ + "", # exports all packages containing package-info.java + ], + "checkstyle" : "org.graalvm.word", "javaCompliance" : "1.8", - "workingSets" : "API,Graal", + "workingSets" : "API,SDK", }, + "org.graalvm.word" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "dependencies" : [], + "checkstyle" : "org.graalvm.word", + "javaCompliance" : "1.8", + "workingSets" : "API,SDK", + }, + + # ------------- Graal ------------- "org.graalvm.compiler.serviceprovider" : { "subDir" : "share/classes", @@ -90,9 +105,11 @@ suite = { "org.graalvm.compiler.options" : { "subDir" : "share/classes", - "dependencies" : ["JVMCI_SERVICES", "JVMCI_API"], + "dependencies" : ["JVMCI_SERVICES", "JVMCI_API", "org.graalvm.util"], "sourceDirs" : ["src"], + "dependencies" : ["org.graalvm.util"], "checkstyle" : "org.graalvm.compiler.graph", + "uses" : ["org.graalvm.compiler.options.OptionDescriptors"], "javaCompliance" : "1.8", "workingSets" : "Graal", }, @@ -124,6 +141,10 @@ suite = { "subDir" : "share/classes", "sourceDirs" : ["src"], "checkstyle" : "org.graalvm.compiler.graph", + "uses" : [ + "org.graalvm.compiler.debug.DebugHandlersFactory", + "org.graalvm.compiler.debug.TTYStreamProvider", + ], "dependencies" : [ "JVMCI_API", "org.graalvm.compiler.serviceprovider", @@ -151,7 +172,6 @@ suite = { "sourceDirs" : ["src"], "dependencies" : [ "org.graalvm.compiler.graph", - "org.graalvm.compiler.common", ], "annotationProcessors" : ["GRAAL_SERVICEPROVIDER_PROCESSOR"], "checkstyle" : "org.graalvm.compiler.graph", @@ -159,7 +179,7 @@ suite = { "workingSets" : "Graal", }, - "org.graalvm.compiler.api.collections" : { + "org.graalvm.graphio" : { "subDir" : "share/classes", "sourceDirs" : ["src"], "checkstyle" : "org.graalvm.compiler.graph", @@ -167,6 +187,26 @@ suite = { "workingSets" : "API,Graal", }, + "org.graalvm.util" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "checkstyle" : "org.graalvm.compiler.graph", + "javaCompliance" : "1.8", + "workingSets" : "API,Graal", + }, + + "org.graalvm.util.test" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "dependencies" : [ + "mx:JUNIT", + "org.graalvm.util", + ], + "checkstyle" : "org.graalvm.compiler.graph", + "javaCompliance" : "1.8", + "workingSets" : "API,Graal", + }, + "org.graalvm.compiler.api.directives" : { "subDir" : "share/classes", "sourceDirs" : ["src"], @@ -227,8 +267,14 @@ suite = { "JVMCI_HOTSPOT", "org.graalvm.compiler.api.runtime", "org.graalvm.compiler.replacements", + "org.graalvm.compiler.printer", "org.graalvm.compiler.runtime", ], + "imports" : [ + # All other internal packages are exported dynamically - + # see org.graalvm.compiler.hotspot.HotSpotGraalJVMCIServiceLocator + "jdk.internal.module", + ], "checkstyle" : "org.graalvm.compiler.graph", "annotationProcessors" : [ "GRAAL_NODEINFO_PROCESSOR", @@ -372,7 +418,6 @@ suite = { "dependencies" : [ "org.graalvm.compiler.nodeinfo", "org.graalvm.compiler.core.common", - "org.graalvm.compiler.api.collections", ], "javaCompliance" : "1.8", "annotationProcessors" : [ @@ -401,6 +446,7 @@ suite = { "sourceDirs" : ["src"], "dependencies" : [ "JVMCI_API", + "org.graalvm.compiler.core.common" ], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", @@ -411,7 +457,6 @@ suite = { "subDir" : "share/classes", "sourceDirs" : ["src"], "dependencies" : [ - "org.graalvm.compiler.debug", "org.graalvm.compiler.asm", ], "checkstyle" : "org.graalvm.compiler.graph", @@ -434,9 +479,7 @@ suite = { "subDir" : "share/classes", "sourceDirs" : ["src"], "dependencies" : [ - "org.graalvm.compiler.debug", "org.graalvm.compiler.asm", - "org.graalvm.compiler.common" ], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", @@ -688,7 +731,6 @@ suite = { "org.graalvm.compiler.bytecode", "org.graalvm.compiler.lir", ], - "generatedDependencies" : ["org.graalvm.compiler.serviceprovider"], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", "annotationProcessors" : [ @@ -757,6 +799,36 @@ suite = { "workingSets" : "Graal,Phases", }, + "org.graalvm.compiler.virtual.bench" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "dependencies" : ["mx:JMH_1_18", "org.graalvm.compiler.microbenchmarks"], + "checkstyle" : "org.graalvm.compiler.graph", + "javaCompliance" : "1.8", + "annotationProcessors" : ["mx:JMH_1_18"], + "findbugsIgnoresGenerated" : True, + "workingSets" : "Graal,Bench", + "isTestProject" : True, + }, + + "org.graalvm.compiler.microbenchmarks" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "dependencies" : [ + "mx:JMH_1_18", + "org.graalvm.compiler.api.test", + "org.graalvm.compiler.java", + "org.graalvm.compiler.runtime", + ], + "checkstyle" : "org.graalvm.compiler.graph", + "javaCompliance" : "1.8", + "checkPackagePrefix" : "false", + "annotationProcessors" : ["mx:JMH_1_18"], + "findbugsIgnoresGenerated" : True, + "workingSets" : "Graal,Bench", + "isTestProject" : True, + }, + "org.graalvm.compiler.loop" : { "subDir" : "share/classes", "sourceDirs" : ["src"], @@ -767,6 +839,18 @@ suite = { "workingSets" : "Graal", }, + "org.graalvm.compiler.loop.test" : { + "subDir" : "share/classes", + "sourceDirs" : ["src"], + "dependencies" : [ + "org.graalvm.compiler.loop", + "org.graalvm.compiler.core.test" + ], + "checkstyle" : "org.graalvm.compiler.graph", + "javaCompliance" : "1.8", + "workingSets" : "Graal,Test", + }, + "org.graalvm.compiler.loop.phases" : { "subDir" : "share/classes", "sourceDirs" : ["src"], @@ -787,6 +871,7 @@ suite = { "org.graalvm.compiler.virtual", "org.graalvm.compiler.loop.phases", ], + "uses" : ["org.graalvm.compiler.core.match.MatchStatementSet"], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", "annotationProcessors" : [ @@ -922,6 +1007,7 @@ suite = { "sourceDirs" : ["src"], "dependencies" : [ "org.graalvm.compiler.debug", + "org.graalvm.word", ], "annotationProcessors" : ["GRAAL_OPTIONS_PROCESSOR"], "checkstyle" : "org.graalvm.compiler.graph", @@ -933,6 +1019,7 @@ suite = { "subDir" : "share/classes", "sourceDirs" : ["src"], "dependencies" : [ + "org.graalvm.graphio", "org.graalvm.compiler.core", "org.graalvm.compiler.java", ], @@ -949,6 +1036,8 @@ suite = { "subDir" : "share/classes", "sourceDirs" : ["src"], "dependencies" : [ + "org.graalvm.compiler.debug", + "org.graalvm.util", "mx:JUNIT", ], "checkstyle" : "org.graalvm.compiler.graph", @@ -969,6 +1058,7 @@ suite = { "JAVA_ALLOCATION_INSTRUMENTER", "ASM_TREE5", ], + "uses" : ["org.graalvm.compiler.options.OptionDescriptors"], "annotationProcessors" : ["GRAAL_NODEINFO_PROCESSOR"], "checkstyle" : "org.graalvm.compiler.graph", "javaCompliance" : "1.8", @@ -989,21 +1079,6 @@ suite = { "findbugs" : "false", }, - # ------------- Salver ------------- - - "org.graalvm.compiler.salver" : { - "subDir" : "share/classes", - "sourceDirs" : ["src"], - "dependencies" : ["org.graalvm.compiler.phases"], - "annotationProcessors" : [ - "GRAAL_OPTIONS_PROCESSOR", - "GRAAL_SERVICEPROVIDER_PROCESSOR", - ], - "checkstyle" : "org.graalvm.compiler.graph", - "javaCompliance" : "1.8", - "workingSets" : "Graal", - }, - # ------------- AOT ------------- "jdk.tools.jaotc" : { @@ -1031,34 +1106,12 @@ suite = { "jdk.tools.jaotc.binformat" : { "subDir" : "../jdk.aot/share/classes", "sourceDirs" : ["src"], - "dependencies" : [ - "jdk.tools.jaotc.jnilibelf", - ], "generatedDependencies" : [ "org.graalvm.compiler.hotspot", ], "checkstyle" : "jdk.tools.jaotc", "javaCompliance" : "1.8", }, - - "jdk.tools.jaotc.jnilibelf" : { - "subDir" : "../jdk.aot/share/classes", - "sourceDirs" : ["src"], - "dependencies" : [], - "checkstyle" : "jdk.tools.jaotc", - "javaCompliance" : "1.8", - }, - - "jdk.tools.jaotc.jnilibelf.test" : { - "subDir" : "../../test/compiler/aot", - "sourceDirs" : ["src"], - "dependencies" : [ - "jdk.tools.jaotc.jnilibelf", - ], - "checkstyle" : "jdk.tools.jaotc", - "javaCompliance" : "1.8", - }, - }, "distributions" : { @@ -1072,6 +1125,13 @@ suite = { ], }, + "GRAAL_GRAPHIO" : { + "subDir" : "share/classes", + "dependencies" : ["org.graalvm.graphio"], + "distDependencies" : [ + ], + }, + "GRAAL_OPTIONS_PROCESSOR" : { "subDir" : "share/classes", "dependencies" : ["org.graalvm.compiler.options.processor"], @@ -1133,11 +1193,11 @@ suite = { "org.graalvm.compiler.replacements.amd64", "org.graalvm.compiler.core.sparc", "org.graalvm.compiler.replacements.sparc", - "org.graalvm.compiler.salver", ], "distDependencies" : [ "GRAAL_API", "GRAAL_COMPILER", + "GRAAL_GRAPHIO", ], }, @@ -1232,6 +1292,7 @@ suite = { "GRAAL" : { "subDir" : "share/classes", "overlaps" : [ + "GRAAL_GRAPHIO", "GRAAL_OPTIONS", "GRAAL_NODEINFO", "GRAAL_API", @@ -1257,7 +1318,6 @@ suite = { "org.graalvm.compiler.replacements.amd64", "org.graalvm.compiler.core.sparc", "org.graalvm.compiler.replacements.sparc", - "org.graalvm.compiler.salver", "org.graalvm.compiler.hotspot.aarch64", "org.graalvm.compiler.hotspot.amd64", "org.graalvm.compiler.hotspot.sparc", diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/module-info.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/module-info.java index 0c96fff59a4..0cae4bc22d9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/module-info.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/module-info.java @@ -32,11 +32,11 @@ module jdk.internal.vm.compiler { uses org.graalvm.compiler.code.DisassemblerProvider; uses org.graalvm.compiler.core.match.MatchStatementSet; - uses org.graalvm.compiler.debug.DebugConfigCustomizer; - uses org.graalvm.compiler.debug.DebugInitializationParticipant; uses org.graalvm.compiler.debug.TTYStreamProvider; uses org.graalvm.compiler.hotspot.CompilerConfigurationFactory; uses org.graalvm.compiler.hotspot.HotSpotBackendFactory; + uses org.graalvm.compiler.hotspot.HotSpotCodeCacheListener; + uses org.graalvm.compiler.options.OptionValuesAccess; uses org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory; exports org.graalvm.compiler.api.directives to jdk.aot; @@ -49,7 +49,6 @@ module jdk.internal.vm.compiler { exports org.graalvm.compiler.core.common to jdk.aot; exports org.graalvm.compiler.core.target to jdk.aot; exports org.graalvm.compiler.debug to jdk.aot; - exports org.graalvm.compiler.debug.internal to jdk.aot; exports org.graalvm.compiler.graph to jdk.aot; exports org.graalvm.compiler.hotspot to jdk.aot; exports org.graalvm.compiler.hotspot.meta to jdk.aot; @@ -64,7 +63,9 @@ module jdk.internal.vm.compiler { exports org.graalvm.compiler.options to jdk.aot; exports org.graalvm.compiler.phases to jdk.aot; exports org.graalvm.compiler.phases.tiers to jdk.aot; + exports org.graalvm.compiler.printer to jdk.aot; exports org.graalvm.compiler.runtime to jdk.aot; exports org.graalvm.compiler.replacements to jdk.aot; exports org.graalvm.compiler.word to jdk.aot; + exports org.graalvm.word to jdk.aot; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/CollectionsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/CollectionsProvider.java deleted file mode 100644 index f8c00882bb7..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/CollectionsProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.api.collections; - -import java.util.Map; -import java.util.Set; - -/** - * A factory for creating collections. - */ -public interface CollectionsProvider { - - /** - * Creates a set that uses reference-equality in place of object-equality when comparing - * entries. - */ - Set newIdentitySet(); - - /** - * Creates a map that uses reference-equality in place of object-equality when comparing keys. - */ - Map newIdentityMap(); - - /** - * Creates a map that uses reference-equality in place of object-equality when comparing keys. - * - * @param expectedMaxSize the expected maximum size of the map - */ - Map newIdentityMap(int expectedMaxSize); - - /** - * Creates a map that uses reference-equality in place of object-equality when comparing keys. - * - * @param initFrom the returned map is populated with the entries in this map - */ - Map newIdentityMap(Map initFrom); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/AllocationInstrumentationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/AllocationInstrumentationTest.java deleted file mode 100644 index 03bd8a7804d..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/AllocationInstrumentationTest.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.api.directives.test; - -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -@SuppressWarnings("try") -public class AllocationInstrumentationTest extends GraalCompilerTest { - - private TinyInstrumentor instrumentor; - - public AllocationInstrumentationTest() { - HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(ClassA.class, "notInlinedMethod"); - method.setNotInlineable(); - - try { - instrumentor = new TinyInstrumentor(AllocationInstrumentationTest.class, "instrumentation"); - } catch (IOException e) { - Assert.fail("unable to initialize the instrumentor: " + e); - } - } - - public static class ClassA { - // This method should be marked as not inlineable - public void notInlinedMethod() { - } - } - - public static boolean allocationWasExecuted; - - private static void resetFlag() { - allocationWasExecuted = false; - } - - static void instrumentation() { - GraalDirectives.instrumentationBeginForPredecessor(); - allocationWasExecuted = true; - GraalDirectives.instrumentationEnd(); - } - - public static void notEscapeSnippet() { - @SuppressWarnings("unused") - ClassA a = new ClassA(); // a does not escape - } - - @Test - public void testNotEscape() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(AllocationInstrumentationTest.class, "notEscapeSnippet", Opcodes.NEW); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "notEscapeSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - resetFlag(); - // The allocation in the snippet does not escape and will be optimized away. We expect - // the instrumentation is removed. - InstalledCode code = getCode(method); - code.executeVarargs(); - Assert.assertFalse("allocation should not take place", allocationWasExecuted); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static void mustEscapeSnippet() { - ClassA a = new ClassA(); - a.notInlinedMethod(); // a escapses - } - - @Test - public void testMustEscape() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(AllocationInstrumentationTest.class, "mustEscapeSnippet", Opcodes.NEW); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "mustEscapeSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - resetFlag(); - // The allocation in the snippet escapes. We expect the instrumentation is preserved. - InstalledCode code = getCode(method); - code.executeVarargs(); - Assert.assertTrue("allocation should take place", allocationWasExecuted); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static void partialEscapeSnippet(boolean condition) { - ClassA a = new ClassA(); - - if (condition) { - a.notInlinedMethod(); // a escapes in the then-clause - } - } - - @Test - public void testPartialEscape() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(AllocationInstrumentationTest.class, "partialEscapeSnippet", Opcodes.NEW); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "partialEscapeSnippet"); - executeExpected(method, null, true); // ensure the method is fully resolved - resetFlag(); - // The allocation in the snippet escapes in the then-clause, and will be relocated to - // this branch. We expect the instrumentation follows and will only be effective when - // the then-clause is taken. - InstalledCode code = getCode(method); - code.executeVarargs(false); - Assert.assertFalse("allocation should not take place", allocationWasExecuted); - code.executeVarargs(true); - Assert.assertTrue("allocation should take place", allocationWasExecuted); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ControlFlowAnchorDirectiveTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ControlFlowAnchorDirectiveTest.java index 57eaeef26f1..1eaf803fc73 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ControlFlowAnchorDirectiveTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ControlFlowAnchorDirectiveTest.java @@ -220,7 +220,7 @@ public class ControlFlowAnchorDirectiveTest extends GraalCompilerTest { @Test public void testClone() { StructuredGraph g = parseEager("preventPeelSnippet", AllowAssumptions.NO); - g.copy(); + g.copy(g.getDebug()); } private static List getNodeCountAnnotations(StructuredGraph graph) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java index 91a14d1630d..4c6fe60dcd4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java @@ -70,7 +70,7 @@ public class DeoptimizeDirectiveTest extends GraalCompilerTest { Result actual; try { actual = new Result(code.executeVarargs(), null); - } catch (Throwable e) { + } catch (Exception e) { actual = new Result(null, e); } @@ -91,4 +91,31 @@ public class DeoptimizeDirectiveTest extends GraalCompilerTest { boolean valid = testDeoptimizeCheckValid(method); Assert.assertTrue("code should still be valid", valid); } + + public static int zeroBranchProbabilitySnippet(boolean flag) { + if (GraalDirectives.injectBranchProbability(0, flag)) { + GraalDirectives.controlFlowAnchor(); // prevent removal of the if + return 1; + } else { + GraalDirectives.controlFlowAnchor(); // prevent removal of the if + return 2; + } + } + + @Test + public void testZeroBranchProbability() { + ResolvedJavaMethod method = getResolvedJavaMethod("zeroBranchProbabilitySnippet"); + Result expected = executeExpected(method, null, true); + + InstalledCode code = getCode(method); + Result actual; + try { + actual = new Result(code.executeVarargs(true), null); + } catch (Exception e) { + actual = new Result(null, e); + } + + assertEquals(expected, actual); + assertFalse("code should be invalidated", code.isValid()); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IsMethodInlineDirectiveTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IsMethodInlineDirectiveTest.java deleted file mode 100644 index 48a1f107320..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IsMethodInlineDirectiveTest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.api.directives.test; - -import org.junit.Test; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class IsMethodInlineDirectiveTest extends GraalCompilerTest { - - public IsMethodInlineDirectiveTest() { - HotSpotResolvedJavaMethod calleeSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(IsMethodInlineDirectiveTest.class, "calleeSnippet"); - calleeSnippet.shouldBeInlined(); - - HotSpotResolvedJavaMethod calleeWithInstrumentationSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(IsMethodInlineDirectiveTest.class, "calleeWithInstrumentationSnippet"); - calleeWithInstrumentationSnippet.shouldBeInlined(); - } - - public static boolean rootMethodSnippet() { - return GraalDirectives.isMethodInlined(); - } - - @SuppressWarnings("try") - @Test - public void testRootMethod() { - ResolvedJavaMethod method = getResolvedJavaMethod("rootMethodSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - // The target method is not inlined. We expect the result to be false. - InstalledCode code = getCode(method); - try { - Result result = new Result(code.executeVarargs(), null); - assertEquals(new Result(false, null), result); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static boolean calleeSnippet() { - return GraalDirectives.isMethodInlined(); - } - - public static boolean callerSnippet() { - return calleeSnippet(); - } - - @Test - public void testInlinedCallee() { - ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - // calleeSnippet will be inlined. We expect the result to be true. - InstalledCode code = getCode(method); - try { - Result result = new Result(code.executeVarargs(), null); - assertEquals(new Result(true, null), result); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - static boolean isCalleeInlined; - static boolean isCallerInlined; - - public static void calleeWithInstrumentationSnippet() { - GraalDirectives.instrumentationBegin(); - isCalleeInlined = GraalDirectives.isMethodInlined(); - GraalDirectives.instrumentationEnd(); - } - - public static void callerSnippet1() { - calleeWithInstrumentationSnippet(); - - GraalDirectives.instrumentationBegin(); - isCallerInlined = GraalDirectives.isMethodInlined(); - GraalDirectives.instrumentationEnd(); - } - - @SuppressWarnings("try") - @Test - public void testInlinedCalleeWithInstrumentation() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet1"); - executeExpected(method, null); // ensure the method is fully resolved - isCalleeInlined = false; - isCallerInlined = false; - // calleeWithInstrumentationSnippet will be inlined. We expect the flag1 set in - // calleeWithInstrumentationSnippet to be true, and the flag2 set in callerSnippet1 to - // be false. - InstalledCode code = getCode(method); - code.executeVarargs(); - assertTrue("calleWithInstrumentationSnippet should be inlined", isCalleeInlined); - assertFalse("callerSnippet1 should not be inlined", isCallerInlined); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/LockInstrumentationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/LockInstrumentationTest.java deleted file mode 100644 index 244e2d620cc..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/LockInstrumentationTest.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.api.directives.test; - -import java.io.IOException; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -@SuppressWarnings("try") -public class LockInstrumentationTest extends GraalCompilerTest { - - private TinyInstrumentor instrumentor; - - public LockInstrumentationTest() { - HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(ClassA.class, "notInlinedMethod"); - method.setNotInlineable(); - - try { - instrumentor = new TinyInstrumentor(LockInstrumentationTest.class, "instrumentation"); - } catch (IOException e) { - Assert.fail("unable to initialize the instrumentor: " + e); - } - } - - public static class ClassA { - - // This method should be marked as not inlineable - public void notInlinedMethod() { - } - - } - - public static final Object lock = new Object(); - public static boolean lockAfterCheckPoint; - public static boolean checkpoint; - - private static void resetFlags() { - lockAfterCheckPoint = false; - checkpoint = false; - } - - static void instrumentation() { - GraalDirectives.instrumentationBeginForPredecessor(); - lockAfterCheckPoint = checkpoint; - GraalDirectives.instrumentationEnd(); - } - - public static void lockSnippet() { - synchronized (lock) { - checkpoint = true; - ClassA a = new ClassA(); - a.notInlinedMethod(); - } - } - - @Test - public void testLock() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(LockInstrumentationTest.class, "lockSnippet", Opcodes.MONITORENTER); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "lockSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - resetFlags(); - // The monitorenter anchors. We expect the instrumentation set the flag before passing - // the checkpoint. - InstalledCode code = getCode(method); - code.executeVarargs(); - Assert.assertFalse("expected lock was performed before checkpoint", lockAfterCheckPoint); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static void postponeLockSnippet() { - ClassA a = new ClassA(); - - synchronized (a) { - checkpoint = true; - a.notInlinedMethod(); - } - - } - - @Test - public void testNonEscapeLock() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - Class clazz = instrumentor.instrument(LockInstrumentationTest.class, "postponeLockSnippet", Opcodes.MONITORENTER); - ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "postponeLockSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - resetFlags(); - // The lock in the snippet will be relocated before the invocation to - // notInlinedMethod(), i.e., after the checkpoint. We expect the instrumentation follows - // and flag will be set to true. - InstalledCode code = getCode(method); - code.executeVarargs(); - Assert.assertTrue("expected lock was performed after checkpoint", lockAfterCheckPoint); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java index fe5ef07bcc1..311aabba0b9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ProbabilityDirectiveTest.java @@ -22,15 +22,16 @@ */ package org.graalvm.compiler.api.directives.test; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode; +import org.junit.Assert; +import org.junit.Test; public class ProbabilityDirectiveTest extends GraalCompilerTest { @@ -55,9 +56,21 @@ public class ProbabilityDirectiveTest extends GraalCompilerTest { Assert.assertEquals("IfNode count", 1, ifNodes.count()); IfNode ifNode = ifNodes.first(); - AbstractBeginNode trueSuccessor = ifNode.trueSuccessor(); - Assert.assertEquals("branch probability of " + ifNode, 0.125, ifNode.probability(trueSuccessor), 0); + AbstractBeginNode oneSuccessor; + if (returnValue(ifNode.trueSuccessor()) == 1) { + oneSuccessor = ifNode.trueSuccessor(); + } else { + assert returnValue(ifNode.falseSuccessor()) == 1; + oneSuccessor = ifNode.falseSuccessor(); + } + Assert.assertEquals("branch probability of " + ifNode, 0.125, ifNode.probability(oneSuccessor), 0); return true; } + + private static int returnValue(AbstractBeginNode b) { + ControlFlowAnchorNode anchor = (ControlFlowAnchorNode) b.next(); + ReturnNode returnNode = (ReturnNode) anchor.next(); + return returnNode.result().asJavaConstant().asInt(); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/RootNameDirectiveTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/RootNameDirectiveTest.java deleted file mode 100644 index a22ac2edb03..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/RootNameDirectiveTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.api.directives.test; - -import java.io.ByteArrayOutputStream; -import java.lang.reflect.Method; -import java.util.Formatter; -import java.util.HashMap; -import java.util.Map; - -import org.junit.Assert; -import org.junit.Test; - -import com.google.monitoring.runtime.instrumentation.common.com.google.common.base.Objects; -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; -import org.graalvm.compiler.printer.IdealGraphPrinter; - -import jdk.vm.ci.code.CodeCacheProvider; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class RootNameDirectiveTest extends GraalCompilerTest { - - public RootNameDirectiveTest() { - HotSpotResolvedJavaMethod rootNameAtCalleeSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(RootNameDirectiveTest.class, "rootNameAtCalleeSnippet"); - rootNameAtCalleeSnippet.shouldBeInlined(); - - HotSpotResolvedJavaMethod rootNameWithinInstrumentationSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(RootNameDirectiveTest.class, "rootNameWithinInstrumentationSnippet"); - rootNameWithinInstrumentationSnippet.shouldBeInlined(); - } - - private static String toString(ResolvedJavaMethod method) { - return method.getDeclaringClass().toJavaName() + "." + method.getName() + method.getSignature().toMethodDescriptor(); - } - - public static String rootNameSnippet() { - return GraalDirectives.rootName(); - } - - @Test - public void testRootName() { - ResolvedJavaMethod method = getResolvedJavaMethod("rootNameSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - // The target snippet is already the root method. We expect the name of the target snippet - // is returned. - InstalledCode code = getCode(method); - try { - Result result = new Result(code.executeVarargs(), null); - assertEquals(new Result(toString(method), null), result); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - public static String rootNameAtCalleeSnippet() { - return GraalDirectives.rootName(); - } - - public static String callerSnippet() { - return rootNameAtCalleeSnippet(); - } - - @Test - public void testRootNameAtCallee() { - ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet"); - executeExpected(method, null); // ensure the method is fully resolved - // The target snippet is the compilation root of rootNameAtCalleeSnippet() because the later - // will be inlined. We expect the name of the target snippet is returned. - InstalledCode code = getCode(method); - try { - Result result = new Result(code.executeVarargs(), null); - assertEquals(new Result(toString(method), null), result); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - - static String rootNameInCallee; - static String rootNameInCaller; - - @BytecodeParserForceInline - public static void rootNameWithinInstrumentationSnippet() { - GraalDirectives.instrumentationBegin(); - rootNameInCallee = GraalDirectives.rootName(); - GraalDirectives.instrumentationEnd(); - } - - public static void callerSnippet1() { - rootNameWithinInstrumentationSnippet(); - - GraalDirectives.instrumentationBegin(); - rootNameInCaller = GraalDirectives.rootName(); - GraalDirectives.instrumentationEnd(); - } - - @SuppressWarnings("try") - private void assertEquals(StructuredGraph graph, InstalledCode code, Object expected, Object actual) { - if (!Objects.equal(expected, actual)) { - Formatter buf = new Formatter(); - - try (Scope s = Debug.sandbox("PrintingGraph", null)) { - Map properties = new HashMap<>(); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - IdealGraphPrinter printer = new IdealGraphPrinter(baos, true, getSnippetReflection()); - printer.beginGroup("RootNameDirectiveTest", "RootNameDirectiveTest", graph.method(), -1, null); - properties.put("graph", graph.toString()); - properties.put("scope", Debug.currentScope()); - printer.print(graph, graph.method().format("%H.%n(%p)"), properties); - printer.endGroup(); - printer.close(); - buf.format("-- Graph -- %n%s", baos.toString()); - } catch (Throwable e) { - buf.format("%nError printing graph: %s", e); - } - try { - CodeCacheProvider codeCache = getCodeCache(); - Method disassemble = codeCache.getClass().getMethod("disassemble", InstalledCode.class); - buf.format("%n-- Code -- %n%s", disassemble.invoke(codeCache, code)); - } catch (NoSuchMethodException e) { - // Not a HotSpotCodeCacheProvider - } catch (Exception e) { - buf.format("%nError disassembling code: %s", e); - } - Assert.assertEquals(buf.toString(), expected, actual); - } - } - - @SuppressWarnings("try") - @Test - public void testRootNameWithinInstrumentationAtCallee() { - try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) { - ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet1"); - executeExpected(method, null); // ensure the method is fully resolved - rootNameInCallee = null; - rootNameInCaller = null; - // We expect both rootName1 and rootName2 are set to the name of the target snippet. - StructuredGraph graph = parseForCompile(method); - InstalledCode code = getCode(method, graph); - code.executeVarargs(); - assertEquals(graph, code, toString(method), rootNameInCallee); - assertEquals(graph, code, rootNameInCallee, rootNameInCaller); - } catch (Throwable e) { - throw new AssertionError(e); - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/TinyInstrumentor.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/TinyInstrumentor.java deleted file mode 100644 index d8cf15a17fb..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/TinyInstrumentor.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.api.directives.test; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.graalvm.compiler.test.ExportingClassLoader; - -import jdk.internal.org.objectweb.asm.ClassReader; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode; -import jdk.internal.org.objectweb.asm.tree.ClassNode; -import jdk.internal.org.objectweb.asm.tree.IincInsnNode; -import jdk.internal.org.objectweb.asm.tree.InsnList; -import jdk.internal.org.objectweb.asm.tree.JumpInsnNode; -import jdk.internal.org.objectweb.asm.tree.LabelNode; -import jdk.internal.org.objectweb.asm.tree.LineNumberNode; -import jdk.internal.org.objectweb.asm.tree.MethodNode; -import jdk.internal.org.objectweb.asm.tree.VarInsnNode; - -/** - * The {@code TinyInstrumentor} is a bytecode instrumentor using ASM bytecode manipulation - * framework. It injects given code snippet into a target method and creates a temporary class as - * the container. Because the target method is cloned into the temporary class, it is required that - * the target method is public static. Any referred method/field in the target method or the - * instrumentation snippet should be made public as well. - */ -public class TinyInstrumentor implements Opcodes { - - private InsnList instrumentationInstructions; - private int instrumentationMaxLocal; - - /** - * Create a instrumentor with a instrumentation snippet. The snippet is specified with the given - * class {@code instrumentationClass} and the given method name {@code methodName}. - */ - public TinyInstrumentor(Class instrumentationClass, String methodName) throws IOException { - MethodNode instrumentationMethod = getMethodNode(instrumentationClass, methodName); - assert instrumentationMethod != null; - assert (instrumentationMethod.access | ACC_STATIC) != 0; - assert "()V".equals(instrumentationMethod.desc); - instrumentationInstructions = cloneInstructions(instrumentationMethod.instructions); - instrumentationMaxLocal = instrumentationMethod.maxLocals; - // replace return instructions with a goto unless there is a single return at the end. In - // that case, simply remove the return. - List returnInstructions = new ArrayList<>(); - for (AbstractInsnNode instruction : selectAll(instrumentationInstructions)) { - if (instruction instanceof LineNumberNode) { - instrumentationInstructions.remove(instruction); - } else if (instruction.getOpcode() == RETURN) { - returnInstructions.add(instruction); - } - } - LabelNode exit = new LabelNode(); - if (returnInstructions.size() == 1) { - AbstractInsnNode returnInstruction = returnInstructions.get(0); - if (instrumentationInstructions.getLast() != returnInstruction) { - instrumentationInstructions.insertBefore(returnInstruction, new JumpInsnNode(GOTO, exit)); - } - instrumentationInstructions.remove(returnInstruction); - } else { - for (AbstractInsnNode returnInstruction : returnInstructions) { - instrumentationInstructions.insertBefore(returnInstruction, new JumpInsnNode(GOTO, exit)); - instrumentationInstructions.remove(returnInstruction); - } - } - instrumentationInstructions.add(exit); - } - - /** - * @return a {@link MethodNode} called {@code methodName} in the given class. - */ - private static MethodNode getMethodNode(Class clazz, String methodName) throws IOException { - ClassReader classReader = new ClassReader(clazz.getName()); - ClassNode classNode = new ClassNode(); - classReader.accept(classNode, ClassReader.SKIP_FRAMES); - - for (MethodNode methodNode : classNode.methods) { - if (methodNode.name.equals(methodName)) { - return methodNode; - } - } - return null; - } - - /** - * Create a {@link ClassNode} with empty constructor. - */ - private static ClassNode emptyClass(String name) { - ClassNode classNode = new ClassNode(); - classNode.visit(52, ACC_SUPER | ACC_PUBLIC, name.replace('.', '/'), null, "java/lang/Object", new String[]{}); - - MethodVisitor mv = classNode.visitMethod(ACC_PUBLIC, "", "()V", null, null); - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mv.visitInsn(RETURN); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 1); - mv.visitEnd(); - - return classNode; - } - - /** - * Helper method for iterating the given {@link InsnList}. - */ - private static Iterable selectAll(InsnList instructions) { - return new Iterable() { - @Override - public Iterator iterator() { - return instructions.iterator(); - } - }; - } - - /** - * Make a clone of the given {@link InsnList}. - */ - private static InsnList cloneInstructions(InsnList instructions) { - Map labelMap = new HashMap<>(); - for (AbstractInsnNode instruction : selectAll(instructions)) { - if (instruction instanceof LabelNode) { - LabelNode clone = new LabelNode(new Label()); - LabelNode original = (LabelNode) instruction; - labelMap.put(original, clone); - } - } - InsnList clone = new InsnList(); - for (AbstractInsnNode insn : selectAll(instructions)) { - clone.add(insn.clone(labelMap)); - } - return clone; - } - - /** - * Shifts all local variable slot references by a specified amount. - */ - private static void shiftLocalSlots(InsnList instructions, int offset) { - for (AbstractInsnNode insn : selectAll(instructions)) { - if (insn instanceof VarInsnNode) { - VarInsnNode varInsn = (VarInsnNode) insn; - varInsn.var += offset; - - } else if (insn instanceof IincInsnNode) { - IincInsnNode iincInsn = (IincInsnNode) insn; - iincInsn.var += offset; - } - } - } - - /** - * Instrument the target method specified by the class {@code targetClass} and the method name - * {@code methodName}. For each occurrence of the {@code opcode}, the instrumentor injects a - * copy of the instrumentation snippet. - */ - public Class instrument(Class targetClass, String methodName, int opcode) throws IOException, ClassNotFoundException { - return instrument(targetClass, methodName, opcode, true); - } - - public Class instrument(Class targetClass, String methodName, int opcode, boolean insertAfter) throws IOException, ClassNotFoundException { - // create a container class - String className = targetClass.getName() + "$$" + methodName; - ClassNode classNode = emptyClass(className); - // duplicate the target method and add to the container class - MethodNode methodNode = getMethodNode(targetClass, methodName); - MethodNode newMethodNode = new MethodNode(methodNode.access, methodNode.name, methodNode.desc, methodNode.signature, methodNode.exceptions.toArray(new String[methodNode.exceptions.size()])); - methodNode.accept(newMethodNode); - classNode.methods.add(newMethodNode); - // perform bytecode instrumentation - for (AbstractInsnNode instruction : selectAll(newMethodNode.instructions)) { - if (instruction.getOpcode() == opcode) { - InsnList instrumentation = cloneInstructions(instrumentationInstructions); - shiftLocalSlots(instrumentation, newMethodNode.maxLocals); - newMethodNode.maxLocals += instrumentationMaxLocal; - if (insertAfter) { - newMethodNode.instructions.insert(instruction, instrumentation); - } else { - newMethodNode.instructions.insertBefore(instruction, instrumentation); - } - } - } - // dump a byte array and load the class with a dedicated loader to separate the namespace - ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES); - classNode.accept(classWriter); - byte[] bytes = classWriter.toByteArray(); - return new Loader(className, bytes).findClass(className); - } - - private static class Loader extends ExportingClassLoader { - - private String className; - private byte[] bytes; - - Loader(String className, byte[] bytes) { - super(TinyInstrumentor.class.getClassLoader()); - this.className = className; - this.bytes = bytes; - } - - @Override - protected Class findClass(String name) throws ClassNotFoundException { - if (name.equals(className)) { - return defineClass(name, bytes, 0, bytes.length); - } else { - return super.findClass(name); - } - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java index 35bb6686845..aa23c861a4a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java @@ -22,8 +22,6 @@ */ package org.graalvm.compiler.api.directives; -import java.nio.charset.Charset; - // JaCoCo Exclude /** @@ -367,67 +365,4 @@ public final class GraalDirectives { */ public static void ensureVirtualizedHere(@SuppressWarnings("unused") Object object) { } - - /** - * Marks the beginning of an instrumentation boundary. The instrumentation code will be folded - * during compilation and will not affect inlining heuristics regarding graph size except one on - * compiled low-level graph size (e.g., {@code GraalOptions.SmallCompiledLowLevelGraphSize}). - */ - public static void instrumentationBegin() { - } - - /** - * Marks the beginning of an instrumentation boundary and associates the instrumentation with - * the preceding bytecode. If the instrumented instruction is {@code new}, then instrumentation - * will adapt to optimizations concerning allocation, and only be executed if allocation really - * happens. - * - * Example (the instrumentation is associated with {@code new}): - * - *
    - * - *
    -     *  0  new java.lang.Object
    -     *  3  invokestatic org.graalvm.compiler.api.directives.GraalDirectives.instrumentationBeginForPredecessor() : void
    -     *  6  invokestatic AllocationProfiler.countActualAllocation() : void
    -     *  9  invokestatic org.graalvm.compiler.api.directives.GraalDirectives.instrumentationEnd() : void
    -     * 12  invokespecial java.lang.Object()
    -     * 
    - * - *
    - * - * @see #instrumentationBegin() - */ - public static void instrumentationBeginForPredecessor() { - } - - /** - * Marks the end of the instrumentation boundary. - * - * @see #instrumentationBegin() - */ - public static void instrumentationEnd() { - } - - /** - * @return true if the enclosing method is inlined. - */ - public static boolean isMethodInlined() { - return false; - } - - private static final Charset UTF8 = Charset.forName("UTF-8"); - - /** - * @return the name of the root method for the current compilation task. If the enclosing method - * is inlined, it returns the name of the method into which it is inlined. - */ - public static String rootName() { - return new String(rawRootName(), UTF8); - } - - public static byte[] rawRootName() { - return new byte[0]; - } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java index 8b904f36561..08cbae1ce6c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java @@ -54,4 +54,13 @@ public @interface Snippet { @Target(ElementType.PARAMETER) public @interface ConstantParameter { } + + /** + * Denotes a snippet parameter that will bound to a non-null value during snippet template + * instantiation. + */ + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.PARAMETER) + public @interface NonNullParameter { + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.test/src/org/graalvm/compiler/api/test/Graal.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.test/src/org/graalvm/compiler/api/test/Graal.java index 82268194cbd..034ee954987 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.test/src/org/graalvm/compiler/api/test/Graal.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.test/src/org/graalvm/compiler/api/test/Graal.java @@ -24,13 +24,13 @@ package org.graalvm.compiler.api.test; import java.util.Formatter; +import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; +import org.graalvm.compiler.api.runtime.GraalRuntime; + import jdk.vm.ci.runtime.JVMCI; import jdk.vm.ci.runtime.JVMCICompiler; import jdk.vm.ci.services.Services; -import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; -import org.graalvm.compiler.api.runtime.GraalRuntime; - /** * Access point for {@linkplain #getRuntime() retrieving} the {@link GraalRuntime} instance of the * system compiler from unit tests. diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64MacroAssemblerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64MacroAssemblerTest.java index 8bc7e55ecec..be74fd7c167 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64MacroAssemblerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64MacroAssemblerTest.java @@ -31,7 +31,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java index 9934218b662..9c579967920 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java @@ -226,12 +226,12 @@ class TestProtectedAssembler extends AArch64Assembler { } @Override - protected void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { + public void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { super.adds(size, dst, src1, src2, shiftType, imm); } @Override - protected void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { + public void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { super.subs(size, dst, src1, src2, shiftType, imm); } @@ -261,7 +261,7 @@ class TestProtectedAssembler extends AArch64Assembler { } @Override - protected void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) { + public void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) { super.subs(size, dst, src1, src2, extendType, shiftAmt); } @@ -336,7 +336,7 @@ class TestProtectedAssembler extends AArch64Assembler { } @Override - protected void rbit(int size, Register dst, Register src) { + public void rbit(int size, Register dst, Register src) { super.rbit(size, dst, src); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java index 31d07c5b9c0..b86b2c4e26b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.asm.aarch64; import static jdk.vm.ci.aarch64.AArch64.zr; import org.graalvm.compiler.asm.AbstractAddress; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.aarch64.AArch64; @@ -274,7 +274,7 @@ public final class AArch64Address extends AbstractAddress { /** * @return immediate in correct representation for the given addressing mode. For example in * case of addressingMode ==IMMEDIATE_UNSCALED the value will be returned - * as the 9bit signed representation. + * as the 9-bit signed representation. */ public int getImmediate() { switch (addressingMode) { @@ -282,12 +282,15 @@ public final class AArch64Address extends AbstractAddress { case IMMEDIATE_POST_INDEXED: case IMMEDIATE_PRE_INDEXED: // 9-bit signed value + assert NumUtil.isSignedNbit(9, immediate); return immediate & NumUtil.getNbitNumberInt(9); case IMMEDIATE_SCALED: // Unsigned value can be returned as-is. + assert NumUtil.isUnsignedNbit(12, immediate); return immediate; case PC_LITERAL: // 21-bit signed value, but lower 2 bits are always 0 and are shifted out. + assert NumUtil.isSignedNbit(19, immediate >> 2); return (immediate >> 2) & NumUtil.getNbitNumberInt(19); default: throw GraalError.shouldNotReachHere("Should only be called for addressing modes that use immediate values."); @@ -356,4 +359,29 @@ public final class AArch64Address extends AbstractAddress { } } + /** + * Loads an address into Register r. + * + * @param masm the macro assembler. + * @param r general purpose register. May not be null. + */ + public void lea(AArch64MacroAssembler masm, Register r) { + switch (addressingMode) { + case IMMEDIATE_UNSCALED: + if (immediate == 0 && base.equals(r)) { // it's a nop + break; + } + masm.add(64, r, base, immediate); + break; + case REGISTER_OFFSET: + masm.add(64, r, base, offset); + break; + case PC_LITERAL: { + masm.mov(r, getImmediate()); + break; + } + default: + throw GraalError.shouldNotReachHere(); + } + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java index 02a7eb2d686..9298faf25a1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.asm.aarch64; +import static jdk.vm.ci.aarch64.AArch64.cpuRegisters; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADD; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADDS; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.ADR; @@ -94,6 +95,8 @@ import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.STR; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.STXR; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SUB; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.SUBS; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.TBZ; +import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.TBNZ; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.UBFM; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.UDIV; import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.InstructionType.FP32; @@ -111,7 +114,7 @@ import static jdk.vm.ci.aarch64.AArch64.zr; import java.util.Arrays; import org.graalvm.compiler.asm.Assembler; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode; import org.graalvm.compiler.debug.GraalError; @@ -347,6 +350,11 @@ public abstract class AArch64Assembler extends Assembler { return reg.encoding << RnOffset; } + private static int maskField(int sizeInBits, int n) { + assert NumUtil.isSignedNbit(sizeInBits, n); + return n & NumUtil.getNbitNumberInt(sizeInBits); + } + /** * Enumeration of all different instruction kinds: General32/64 are the general instructions * (integer, branch, etc.), for 32-, respectively 64-bit operands. FP32/64 is the encoding for @@ -448,7 +456,7 @@ public abstract class AArch64Assembler extends Assembler { private static final int LoadStoreFpFlagOffset = 26; private static final int LoadLiteralImmeOffset = 5; - private static final int LoadStorePairOp = 0b101_0_010 << 23; + private static final int LoadStorePairOp = 0b101_0 << 26; @SuppressWarnings("unused") private static final int LoadStorePairPostIndexOp = 0b101_0_001 << 23; @SuppressWarnings("unused") private static final int LoadStorePairPreIndexOp = 0b101_0_011 << 23; private static final int LoadStorePairImm7Offset = 15; @@ -470,6 +478,8 @@ public abstract class AArch64Assembler extends Assembler { BCOND(0x54000000), CBNZ(0x01000000), CBZ(0x00000000), + TBZ(0x36000000), + TBNZ(0x37000000), B(0x00000000), BL(0x80000000), @@ -803,6 +813,82 @@ public abstract class AArch64Assembler extends Assembler { conditionalBranchInstruction(reg, imm21, generalFromSize(size), Instruction.CBZ, pos); } + /** + * Test a single bit and branch if the bit is nonzero. + * + * @param reg general purpose register. May not be null, zero-register or stackpointer. + * @param uimm6 Unsigned 6-bit bit index. + * @param imm16 signed 16 bit offset + */ + protected void tbnz(Register reg, int uimm6, int imm16) { + tbnz(reg, uimm6, imm16, -1); + } + + /** + * Test a single bit and branch if the bit is zero. + * + * @param reg general purpose register. May not be null, zero-register or stackpointer. + * @param uimm6 Unsigned 6-bit bit index. + * @param imm16 signed 16 bit offset + */ + protected void tbz(Register reg, int uimm6, int imm16) { + tbz(reg, uimm6, imm16, -1); + } + + /** + * Test a single bit and branch if the bit is nonzero. + * + * @param reg general purpose register. May not be null, zero-register or stackpointer. + * @param uimm6 Unsigned 6-bit bit index. + * @param imm16 signed 16 bit offset + * @param pos Position at which instruction is inserted into buffer. -1 means insert at end. + */ + protected void tbnz(Register reg, int uimm6, int imm16, int pos) { + assert reg.getRegisterCategory().equals(CPU); + assert NumUtil.isUnsignedNbit(6, uimm6); + assert NumUtil.isSignedNbit(18, imm16); + assert (imm16 & 3) == 0; + // size bit is overloaded as top bit of uimm6 bit index + int size = (((uimm6 >> 5) & 1) == 0 ? 32 : 64); + // remaining 5 bits are encoded lower down + int uimm5 = uimm6 >> 1; + int offset = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2; + InstructionType type = generalFromSize(size); + int encoding = type.encoding | TBNZ.encoding | (uimm5 << 19) | (offset << 5) | rd(reg); + if (pos == -1) { + emitInt(encoding); + } else { + emitInt(encoding, pos); + } + } + + /** + * Test a single bit and branch if the bit is zero. + * + * @param reg general purpose register. May not be null, zero-register or stackpointer. + * @param uimm6 Unsigned 6-bit bit index. + * @param imm16 signed 16 bit offset + * @param pos Position at which instruction is inserted into buffer. -1 means insert at end. + */ + protected void tbz(Register reg, int uimm6, int imm16, int pos) { + assert reg.getRegisterCategory().equals(CPU); + assert NumUtil.isUnsignedNbit(6, uimm6); + assert NumUtil.isSignedNbit(18, imm16); + assert (imm16 & 3) == 0; + // size bit is overloaded as top bit of uimm6 bit index + int size = (((uimm6 >> 5) & 1) == 0 ? 32 : 64); + // remaining 5 bits are encoded lower down + int uimm5 = uimm6 >> 1; + int offset = (imm16 & NumUtil.getNbitNumberInt(16)) >> 2; + InstructionType type = generalFromSize(size); + int encoding = type.encoding | TBZ.encoding | (uimm5 << 19) | (offset << 5) | rd(reg); + if (pos == -1) { + emitInt(encoding); + } else { + emitInt(encoding, pos); + } + } + private void conditionalBranchInstruction(Register reg, int imm21, InstructionType type, Instruction instr, int pos) { assert reg.getRegisterCategory().equals(CPU); int instrEncoding = instr.encoding | CompareBranchOp; @@ -925,6 +1011,100 @@ public abstract class AArch64Assembler extends Assembler { loadStoreInstruction(LDRS, rt, address, generalFromSize(targetSize), transferSize); } + public enum PrefetchMode { + PLDL1KEEP(0b00000), + PLDL1STRM(0b00001), + PLDL2KEEP(0b00010), + PLDL2STRM(0b00011), + PLDL3KEEP(0b00100), + PLDL3STRM(0b00101), + + PLIL1KEEP(0b01000), + PLIL1STRM(0b01001), + PLIL2KEEP(0b01010), + PLIL2STRM(0b01011), + PLIL3KEEP(0b01100), + PLIL3STRM(0b01101), + + PSTL1KEEP(0b10000), + PSTL1STRM(0b10001), + PSTL2KEEP(0b10010), + PSTL2STRM(0b10011), + PSTL3KEEP(0b10100), + PSTL3STRM(0b10101); + + private final int encoding; + + PrefetchMode(int encoding) { + this.encoding = encoding; + } + + private static PrefetchMode[] modes = { + PLDL1KEEP, + PLDL1STRM, + PLDL2KEEP, + PLDL2STRM, + PLDL3KEEP, + PLDL3STRM, + + null, + null, + + PLIL1KEEP, + PLIL1STRM, + PLIL2KEEP, + PLIL2STRM, + PLIL3KEEP, + PLIL3STRM, + + null, + null, + + PSTL1KEEP, + PSTL1STRM, + PSTL2KEEP, + PSTL2STRM, + PSTL3KEEP, + PSTL3STRM + }; + + public static PrefetchMode lookup(int enc) { + assert enc >= 00 && enc < modes.length; + return modes[enc]; + } + + public Register toRegister() { + return cpuRegisters.get(encoding); + } + } + + /* + * implements a prefetch at a 64-bit aligned address using a scaled 12 bit or unscaled 9 bit + * displacement addressing mode + * + * @param rt general purpose register. May not be null, zr or stackpointer. + * + * @param address only displacement addressing modes allowed. May not be null. + */ + public void prfm(AArch64Address address, PrefetchMode mode) { + assert (address.getAddressingMode() == AddressingMode.IMMEDIATE_SCALED || + address.getAddressingMode() == AddressingMode.IMMEDIATE_UNSCALED || + address.getAddressingMode() == AddressingMode.REGISTER_OFFSET); + assert mode != null; + final int srcSize = 64; + final int transferSize = NumUtil.log2Ceil(srcSize / 8); + final Register rt = mode.toRegister(); + // this looks weird but that's because loadStoreInstruction is weird + // instruction select fields are size [31:30], v [26] and opc [25:24] + // prfm requires size == 0b11, v == 0b0 and opc == 0b11 + // passing LDRS ensures opc[1] == 0b1 + // (n.b. passing LDR/STR makes no difference to opc[1:0]!!) + // passing General64 ensures opc[0] == 0b1 and v = 0b0 + // (n.b. passing General32 ensures opc[0] == 0b0 and v = 0b0) + // srcSize 64 ensures size == 0b11 + loadStoreInstruction(LDRS, rt, address, General64, transferSize); + } + /** * Stores register rt into memory pointed by address. * @@ -978,7 +1158,9 @@ public abstract class AArch64Assembler extends Assembler { } /** - * + * Load Pair of Registers calculates an address from a base register value and an immediate + * offset, and stores two 32-bit words or two 64-bit doublewords to the calculated address, from + * two registers. */ public void ldp(int size, Register rt, Register rt2, AArch64Address address) { assert size == 32 || size == 64; @@ -996,10 +1178,18 @@ public abstract class AArch64Assembler extends Assembler { } private void loadStorePairInstruction(Instruction instr, Register rt, Register rt2, AArch64Address address, InstructionType type) { - int memop = type.encoding | instr.encoding | address.getImmediate() << LoadStorePairImm7Offset | rt2(rt2) | rn(address.getBase()) | rt(rt); + int scaledOffset = maskField(7, address.getImmediateRaw()); // LDP/STP use a 7-bit scaled + // offset + int memop = type.encoding | instr.encoding | scaledOffset << LoadStorePairImm7Offset | rt2(rt2) | rn(address.getBase()) | rt(rt); switch (address.getAddressingMode()) { - case IMMEDIATE_UNSCALED: - emitInt(memop | LoadStorePairOp); + case IMMEDIATE_SCALED: + emitInt(memop | LoadStorePairOp | (0b010 << 23)); + break; + case IMMEDIATE_POST_INDEXED: + emitInt(memop | LoadStorePairOp | (0b001 << 23)); + break; + case IMMEDIATE_PRE_INDEXED: + emitInt(memop | LoadStorePairOp | (0b011 << 23)); break; default: throw GraalError.shouldNotReachHere("Unhandled addressing mode: " + address.getAddressingMode()); @@ -1471,7 +1661,7 @@ public abstract class AArch64Assembler extends Assembler { * @param shiftType any type but ROR. * @param imm must be in range 0 to size - 1. */ - protected void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { + public void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { addSubShiftedInstruction(ADDS, dst, src1, src2, shiftType, imm, generalFromSize(size)); } @@ -1499,7 +1689,7 @@ public abstract class AArch64Assembler extends Assembler { * @param shiftType any type but ROR. * @param imm must be in range 0 to size - 1. */ - protected void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { + public void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) { addSubShiftedInstruction(SUBS, dst, src1, src2, shiftType, imm, generalFromSize(size)); } @@ -1571,7 +1761,7 @@ public abstract class AArch64Assembler extends Assembler { * @param extendType defines how src2 is extended to the same size as src1. * @param shiftAmt must be in range 0 to 4. */ - protected void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) { + public void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) { assert !dst.equals(sp); assert !src1.equals(zr); assert !src2.equals(sp); @@ -1786,7 +1976,7 @@ public abstract class AArch64Assembler extends Assembler { * @param dst general purpose register. May not be null, zero-register or the stackpointer. * @param src source register. May not be null, zero-register or the stackpointer. */ - protected void rbit(int size, Register dst, Register src) { + public void rbit(int size, Register dst, Register src) { dataProcessing1SourceOp(RBIT, dst, src, generalFromSize(size)); } @@ -1934,7 +2124,7 @@ public abstract class AArch64Assembler extends Assembler { * @param src2 general purpose register. May not be null or the stackpointer. * @param src3 general purpose register. May not be null or the stackpointer. */ - protected void smaddl(Register dst, Register src1, Register src2, Register src3) { + public void smaddl(Register dst, Register src1, Register src2, Register src3) { assert !dst.equals(sp); assert !src1.equals(sp); assert !src2.equals(sp); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java index 7c0d184e02c..7f111fd0e5c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java @@ -39,7 +39,7 @@ import static jdk.vm.ci.aarch64.AArch64.zr; import org.graalvm.compiler.asm.AbstractAddress; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.aarch64.AArch64; @@ -146,10 +146,10 @@ public class AArch64MacroAssembler extends AArch64Assembler { return new AddressGenerationPlan(ADD_TO_BASE, REGISTER_OFFSET, needsScratch); } } else { - if (NumUtil.isSignedNbit(9, displacement)) { - return new AddressGenerationPlan(NO_WORK, IMMEDIATE_UNSCALED, false); - } else if (displacementScalable && NumUtil.isUnsignedNbit(12, scaledDisplacement)) { + if (displacementScalable && NumUtil.isUnsignedNbit(12, scaledDisplacement)) { return new AddressGenerationPlan(NO_WORK, IMMEDIATE_SCALED, false); + } else if (NumUtil.isSignedNbit(9, displacement)) { + return new AddressGenerationPlan(NO_WORK, IMMEDIATE_UNSCALED, false); } else { boolean needsScratch = !isArithmeticImmediate(displacement); return new AddressGenerationPlan(ADD_TO_BASE, REGISTER_OFFSET, needsScratch); @@ -196,6 +196,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { break; case ADD_TO_INDEX: newIndex = allowOverwrite ? index : additionalReg; + assert !newIndex.equals(sp) && !newIndex.equals(zr); if (plan.needsScratch) { mov(additionalReg, scaledDisplacement); add(signExtendIndex ? 32 : 64, newIndex, index, additionalReg); @@ -206,6 +207,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { break; case ADD_TO_BASE: newBase = allowOverwrite ? base : additionalReg; + assert !newBase.equals(sp) && !newBase.equals(zr); if (plan.needsScratch) { mov(additionalReg, displacement); add(64, newBase, base, additionalReg); @@ -411,6 +413,19 @@ public class AArch64MacroAssembler extends AArch64Assembler { assert !firstMove; } + /** + * Generates a 32-bit immediate move code sequence. The immediate may later be updated by + * HotSpot. + * + * @param dst general purpose register. May not be null, stackpointer or zero-register. + * @param imm + */ + public void movNarrowAddress(Register dst, long imm) { + assert (imm & 0xFFFF_FFFF_0000_0000L) == 0; + movz(64, dst, (int) (imm >>> 16), 16); + movk(64, dst, (int) (imm & 0xffff), 0); + } + /** * @return Number of instructions necessary to load immediate into register. */ @@ -455,6 +470,19 @@ public class AArch64MacroAssembler extends AArch64Assembler { } } + /** + * Loads a srcSize value from address into rt zero-extending it if necessary. + * + * @param srcSize size of memory read in bits. Must be 8, 16 or 32 and smaller or equal to + * targetSize. + * @param rt general purpose register. May not be null or stackpointer. + * @param address all addressing modes allowed. May not be null. + */ + @Override + public void ldr(int srcSize, Register rt, AArch64Address address) { + super.ldr(srcSize, rt, address); + } + /** * Conditional move. dst = src1 if condition else src2. * @@ -482,52 +510,47 @@ public class AArch64MacroAssembler extends AArch64Assembler { * dst = src1 + src2. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src1 general purpose register. May not be null or stackpointer. + * @param dst general purpose register. May not be null. + * @param src1 general purpose register. May not be null. * @param src2 general purpose register. May not be null or stackpointer. */ public void add(int size, Register dst, Register src1, Register src2) { - super.add(size, dst, src1, src2, ShiftType.LSL, 0); + if (dst.equals(sp) || src1.equals(sp)) { + super.add(size, dst, src1, src2, ExtendType.UXTX, 0); + } else { + super.add(size, dst, src1, src2, ShiftType.LSL, 0); + } } /** * dst = src1 + src2 and sets condition flags. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src1 general purpose register. May not be null or stackpointer. + * @param dst general purpose register. May not be null. + * @param src1 general purpose register. May not be null. * @param src2 general purpose register. May not be null or stackpointer. */ public void adds(int size, Register dst, Register src1, Register src2) { - super.adds(size, dst, src1, src2, getNopExtendType(size), 0); + if (dst.equals(sp) || src1.equals(sp)) { + super.adds(size, dst, src1, src2, ExtendType.UXTX, 0); + } else { + super.adds(size, dst, src1, src2, ShiftType.LSL, 0); + } } /** * dst = src1 - src2 and sets condition flags. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src1 general purpose register. May not be null or stackpointer. + * @param dst general purpose register. May not be null. + * @param src1 general purpose register. May not be null. * @param src2 general purpose register. May not be null or stackpointer. */ public void subs(int size, Register dst, Register src1, Register src2) { - super.subs(size, dst, src1, src2, getNopExtendType(size), 0); - } - - /** - * Returns the ExtendType for the given size that corresponds to a no-op. - * - * I.e. when doing add X0, X1, X2, the actual instruction has the form add X0, X1, X2 UXTX. - * - * @param size - */ - private static ExtendType getNopExtendType(int size) { - if (size == 64) { - return ExtendType.UXTX; - } else if (size == 32) { - return ExtendType.UXTW; + if (dst.equals(sp) || src1.equals(sp)) { + super.subs(size, dst, src1, src2, ExtendType.UXTX, 0); } else { - throw GraalError.shouldNotReachHere("No-op "); + super.subs(size, dst, src1, src2, ShiftType.LSL, 0); } } @@ -535,12 +558,16 @@ public class AArch64MacroAssembler extends AArch64Assembler { * dst = src1 - src2. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src1 general purpose register. May not be null or stackpointer. + * @param dst general purpose register. May not be null. + * @param src1 general purpose register. May not be null. * @param src2 general purpose register. May not be null or stackpointer. */ public void sub(int size, Register dst, Register src1, Register src2) { - super.sub(size, dst, src1, src2, ShiftType.LSL, 0); + if (dst.equals(sp) || src1.equals(sp)) { + super.sub(size, dst, src1, src2, ExtendType.UXTX, 0); + } else { + super.sub(size, dst, src1, src2, ShiftType.LSL, 0); + } } /** @@ -590,16 +617,26 @@ public class AArch64MacroAssembler extends AArch64Assembler { * dst = src + immediate. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src general purpose register. May not be null or stackpointer. - * @param immediate arithmetic immediate + * @param dst general purpose register. May not be null or zero-register. + * @param src general purpose register. May not be null or zero-register. + * @param immediate 32-bit signed int */ @Override public void add(int size, Register dst, Register src, int immediate) { + assert (!dst.equals(zr) && !src.equals(zr)); if (immediate < 0) { sub(size, dst, src, -immediate); - } else if (!(dst.equals(src) && immediate == 0)) { - super.add(size, dst, src, immediate); + } else if (isAimm(immediate)) { + if (!(dst.equals(src) && immediate == 0)) { + super.add(size, dst, src, immediate); + } + } else if (immediate >= -(1 << 24) && immediate < (1 << 24)) { + super.add(size, dst, src, immediate & -(1 << 12)); + super.add(size, dst, dst, immediate & ((1 << 12) - 1)); + } else { + assert !dst.equals(src); + mov(dst, immediate); + add(size, src, dst, dst); } } @@ -613,6 +650,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { */ @Override public void adds(int size, Register dst, Register src, int immediate) { + assert (!dst.equals(sp) && !src.equals(zr)); if (immediate < 0) { subs(size, dst, src, -immediate); } else if (!(dst.equals(src) && immediate == 0)) { @@ -624,16 +662,26 @@ public class AArch64MacroAssembler extends AArch64Assembler { * dst = src - immediate. * * @param size register size. Has to be 32 or 64. - * @param dst general purpose register. May not be null or stackpointer. - * @param src general purpose register. May not be null or stackpointer. - * @param immediate arithmetic immediate + * @param dst general purpose register. May not be null or zero-register. + * @param src general purpose register. May not be null or zero-register. + * @param immediate 32-bit signed int */ @Override public void sub(int size, Register dst, Register src, int immediate) { + assert (!dst.equals(zr) && !src.equals(zr)); if (immediate < 0) { add(size, dst, src, -immediate); - } else if (!dst.equals(src) || immediate != 0) { - super.sub(size, dst, src, immediate); + } else if (isAimm(immediate)) { + if (!(dst.equals(src) && immediate == 0)) { + super.sub(size, dst, src, immediate); + } + } else if (immediate >= -(1 << 24) && immediate < (1 << 24)) { + super.sub(size, dst, src, immediate & -(1 << 12)); + super.sub(size, dst, dst, immediate & ((1 << 12) - 1)); + } else { + assert !dst.equals(src); + mov(dst, immediate); + sub(size, src, dst, dst); } } @@ -647,10 +695,11 @@ public class AArch64MacroAssembler extends AArch64Assembler { */ @Override public void subs(int size, Register dst, Register src, int immediate) { + assert (!dst.equals(sp) && !src.equals(zr)); if (immediate < 0) { adds(size, dst, src, -immediate); } else if (!dst.equals(src) || immediate != 0) { - super.sub(size, dst, src, immediate); + super.subs(size, dst, src, immediate); } } @@ -675,6 +724,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param src2 general purpose register. May not be null or the stackpointer. */ public void umulh(int size, Register dst, Register src1, Register src2) { + assert (!dst.equals(sp) && !src1.equals(sp) && !src2.equals(sp)); assert size == 32 || size == 64; if (size == 64) { super.umulh(dst, src1, src2); @@ -695,6 +745,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param src2 general purpose register. May not be null or the stackpointer. */ public void smulh(int size, Register dst, Register src1, Register src2) { + assert (!dst.equals(sp) && !src1.equals(sp) && !src2.equals(sp)); assert size == 32 || size == 64; if (size == 64) { super.smulh(dst, src1, src2); @@ -715,6 +766,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param d denominator. General purpose register. Divisor May not be null or the stackpointer. */ public void rem(int size, Register dst, Register n, Register d) { + assert (!dst.equals(sp) && !n.equals(sp) && !d.equals(sp)); // There is no irem or similar instruction. Instead we use the relation: // n % d = n - Floor(n / d) * d if nd >= 0 // n % d = n - Ceil(n / d) * d else @@ -940,16 +992,14 @@ public class AArch64MacroAssembler extends AArch64Assembler { /** * Sign-extend value from src into dst. * - * @param destSize destination register size. Has to be 32 or 64. - * @param srcSize source register size. May be 8, 16 or 32 and smaller than destSize. + * @param destSize destination register size. Must be 32 or 64. + * @param srcSize source register size. Must be smaller than destSize. * @param dst general purpose register. May not be null, stackpointer or zero-register. * @param src general purpose register. May not be null, stackpointer or zero-register. */ public void sxt(int destSize, int srcSize, Register dst, Register src) { - assert (destSize == 32 || destSize == 64) && srcSize < destSize; - assert srcSize == 8 || srcSize == 16 || srcSize == 32; - int[] srcSizeValues = {7, 15, 31}; - super.sbfm(destSize, dst, src, 0, srcSizeValues[NumUtil.log2Ceil(srcSize / 8)]); + assert (srcSize < destSize && srcSize > 0); + super.sbfm(destSize, dst, src, 0, srcSize - 1); } /** @@ -1078,6 +1128,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param y general purpose register. May not be null or stackpointer. */ public void cmp(int size, Register x, Register y) { + assert size == 32 || size == 64; super.subs(size, zr, x, y, ShiftType.LSL, 0); } @@ -1089,6 +1140,7 @@ public class AArch64MacroAssembler extends AArch64Assembler { * @param y comparison immediate, {@link #isComparisonImmediate(long)} has to be true for it. */ public void cmp(int size, Register x, int y) { + assert size == 32 || size == 64; if (y < 0) { super.adds(size, zr, x, -y); } else { @@ -1108,6 +1160,54 @@ public class AArch64MacroAssembler extends AArch64Assembler { super.ands(size, dst, x, y, ShiftType.LSL, 0); } + /** + * Sets overflow flag according to result of x * y. + * + * @param size register size. Has to be 32 or 64. + * @param dst general purpose register. May not be null or stack-pointer. + * @param x general purpose register. May not be null or stackpointer. + * @param y general purpose register. May not be null or stackpointer. + */ + public void mulvs(int size, Register dst, Register x, Register y) { + try (ScratchRegister sc1 = getScratchRegister(); + ScratchRegister sc2 = getScratchRegister()) { + switch (size) { + case 64: { + // Be careful with registers: it's possible that x, y, and dst are the same + // register. + Register rscratch1 = sc1.getRegister(); + Register rscratch2 = sc2.getRegister(); + mul(64, rscratch1, x, y); // Result bits 0..63 + smulh(64, rscratch2, x, y); // Result bits 64..127 + // Top is pure sign ext + subs(64, zr, rscratch2, rscratch1, ShiftType.ASR, 63); + // Copy all 64 bits of the result into dst + mov(64, dst, rscratch1); + mov(rscratch1, 0x80000000); + // Develop 0 (EQ), or 0x80000000 (NE) + cmov(32, rscratch1, rscratch1, zr, ConditionFlag.NE); + cmp(32, rscratch1, 1); + // 0x80000000 - 1 => VS + break; + } + case 32: { + Register rscratch1 = sc1.getRegister(); + smaddl(rscratch1, x, y, zr); + // Copy the low 32 bits of the result into dst + mov(32, dst, rscratch1); + subs(64, zr, rscratch1, rscratch1, ExtendType.SXTW, 0); + // NE => overflow + mov(rscratch1, 0x80000000); + // Develop 0 (EQ), or 0x80000000 (NE) + cmov(32, rscratch1, rscratch1, zr, ConditionFlag.NE); + cmp(32, rscratch1, 1); + // 0x80000000 - 1 => VS + break; + } + } + } + } + /** * When patching up Labels we have to know what kind of code to generate. */ @@ -1116,8 +1216,10 @@ public class AArch64MacroAssembler extends AArch64Assembler { BRANCH_UNCONDITIONALLY(0x1), BRANCH_NONZERO(0x2), BRANCH_ZERO(0x3), - JUMP_ADDRESS(0x4), - ADR(0x5); + BRANCH_BIT_NONZERO(0x4), + BRANCH_BIT_ZERO(0x5), + JUMP_ADDRESS(0x6), + ADR(0x7); /** * Offset by which additional information for branch conditionally, branch zero and branch @@ -1194,6 +1296,46 @@ public class AArch64MacroAssembler extends AArch64Assembler { } } + /** + * Test a single bit and branch if the bit is nonzero. + * + * @param cmp general purpose register. May not be null, zero-register or stackpointer. + * @param uimm6 Unsigned 6-bit bit index. + * @param label Can only handle 21-bit word-aligned offsets for now. May be unbound. Non null. + */ + public void tbnz(Register cmp, int uimm6, Label label) { + assert NumUtil.isUnsignedNbit(6, uimm6); + if (label.isBound()) { + int offset = label.position() - position(); + super.tbnz(cmp, uimm6, offset); + } else { + label.addPatchAt(position()); + int indexEncoding = uimm6 << PatchLabelKind.INFORMATION_OFFSET; + int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 6); + emitInt(PatchLabelKind.BRANCH_BIT_NONZERO.encoding | indexEncoding | regEncoding); + } + } + + /** + * Test a single bit and branch if the bit is zero. + * + * @param cmp general purpose register. May not be null, zero-register or stackpointer. + * @param uimm6 Unsigned 6-bit bit index. + * @param label Can only handle 21-bit word-aligned offsets for now. May be unbound. Non null. + */ + public void tbz(Register cmp, int uimm6, Label label) { + assert NumUtil.isUnsignedNbit(6, uimm6); + if (label.isBound()) { + int offset = label.position() - position(); + super.tbz(cmp, uimm6, offset); + } else { + label.addPatchAt(position()); + int indexEncoding = uimm6 << PatchLabelKind.INFORMATION_OFFSET; + int regEncoding = cmp.encoding << (PatchLabelKind.INFORMATION_OFFSET + 6); + emitInt(PatchLabelKind.BRANCH_BIT_ZERO.encoding | indexEncoding | regEncoding); + } + } + /** * Branches to label if condition is true. * @@ -1353,7 +1495,8 @@ public class AArch64MacroAssembler extends AArch64Assembler { super.b(branchOffset, branch); break; case JUMP_ADDRESS: - emitInt(jumpTarget, branch); + int offset = instruction >>> PatchLabelKind.INFORMATION_OFFSET; + emitInt(jumpTarget - offset, branch); break; case BRANCH_NONZERO: case BRANCH_ZERO: { @@ -1373,6 +1516,22 @@ public class AArch64MacroAssembler extends AArch64Assembler { } break; } + case BRANCH_BIT_NONZERO: + case BRANCH_BIT_ZERO: { + int information = instruction >>> PatchLabelKind.INFORMATION_OFFSET; + int sizeEncoding = information & NumUtil.getNbitNumberInt(6); + int regEncoding = information >>> 6; + Register reg = AArch64.cpuRegisters.get(regEncoding); + switch (type) { + case BRANCH_BIT_NONZERO: + super.tbnz(reg, sizeEncoding, branchOffset, branch); + break; + case BRANCH_BIT_ZERO: + super.tbz(reg, sizeEncoding, branchOffset, branch); + break; + } + break; + } case ADR: { int information = instruction >>> PatchLabelKind.INFORMATION_OFFSET; int regEncoding = information; @@ -1404,4 +1563,14 @@ public class AArch64MacroAssembler extends AArch64Assembler { public AbstractAddress getPlaceholder(int instructionStartPosition) { return AArch64Address.PLACEHOLDER; } + + /** + * Loads an address into Register d. + * + * @param d general purpose register. May not be null. + * @param a AArch64Address the address of an operand. + */ + public void lea(Register d, AArch64Address a) { + a.lea(this, d); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64.test/src/org/graalvm/compiler/asm/amd64/test/SimpleAssemblerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64.test/src/org/graalvm/compiler/asm/amd64/test/SimpleAssemblerTest.java index a7af5e74a4e..7e7c6cd0245 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64.test/src/org/graalvm/compiler/asm/amd64/test/SimpleAssemblerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64.test/src/org/graalvm/compiler/asm/amd64/test/SimpleAssemblerTest.java @@ -27,6 +27,16 @@ import static org.junit.Assume.assumeTrue; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import org.graalvm.compiler.asm.amd64.AMD64Assembler; +import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.asm.test.AssemblerTest; +import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.code.DataSection.Data; +import org.graalvm.compiler.code.DataSection.RawData; +import org.graalvm.compiler.code.DataSection.SerializableData; +import org.junit.Before; +import org.junit.Test; + import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.Register; @@ -36,17 +46,6 @@ import jdk.vm.ci.code.site.DataSectionReference; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import org.junit.Before; -import org.junit.Test; - -import org.graalvm.compiler.asm.amd64.AMD64Assembler; -import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; -import org.graalvm.compiler.asm.test.AssemblerTest; -import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.compiler.code.DataSection.Data; -import org.graalvm.compiler.code.DataSection.RawData; -import org.graalvm.compiler.code.DataSection.SerializableData; - public class SimpleAssemblerTest extends AssemblerTest { @Before diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Address.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Address.java index 1ff59f79536..7b5bec18025 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Address.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Address.java @@ -65,6 +65,18 @@ public final class AMD64Address extends AbstractAddress { this(base, Register.None, Scale.Times1, displacement); } + /** + * Creates an {@link AMD64Address} with given base and index registers, scaling and 0 + * displacement. + * + * @param base the base register + * @param index the index register + * @param scale the scaling factor + */ + public AMD64Address(Register base, Register index, Scale scale) { + this(base, index, scale, 0, -1); + } + /** * Creates an {@link AMD64Address} with given base and index registers, scaling and * displacement. This is the most general constructor. diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java index a69eb78cd50..56090fa7af3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.asm.amd64; -import static org.graalvm.compiler.asm.NumUtil.isByte; -import static org.graalvm.compiler.asm.NumUtil.isInt; -import static org.graalvm.compiler.asm.NumUtil.isShiftCount; -import static org.graalvm.compiler.asm.NumUtil.isUByte; +import static org.graalvm.compiler.core.common.NumUtil.isByte; +import static org.graalvm.compiler.core.common.NumUtil.isInt; +import static org.graalvm.compiler.core.common.NumUtil.isShiftCount; +import static org.graalvm.compiler.core.common.NumUtil.isUByte; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseAddressNop; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseNormalNop; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.ADD; @@ -58,7 +58,7 @@ import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import jdk.vm.ci.amd64.AMD64; @@ -2494,6 +2494,24 @@ public class AMD64Assembler extends Assembler { emitByte(0xC0 | encode); } + void pcmpestri(Register dst, AMD64Address src, int imm8) { + assert supports(CPUFeature.SSE4_2); + AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target); + simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_3A, attributes); + emitByte(0x61); + emitOperandHelper(dst, src, 0); + emitByte(imm8); + } + + void pcmpestri(Register dst, Register src, int imm8) { + assert supports(CPUFeature.SSE4_2); + AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target); + int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_3A, attributes); + emitByte(0x61); + emitByte(0xC0 | encode); + emitByte(imm8); + } + public final void push(Register src) { int encode = prefixAndEncode(src.encoding); emitByte(0x50 | encode); @@ -2633,6 +2651,16 @@ public class AMD64Assembler extends Assembler { emitByte(imm8); } + public final void psrldq(Register dst, int imm8) { + assert isUByte(imm8) : "invalid value"; + assert dst.getRegisterCategory().equals(AMD64.XMM); + AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target); + int encode = simdPrefixAndEncode(AMD64.xmm3, dst, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes); + emitByte(0x73); + emitByte(0xC0 | encode); + emitByte(imm8); + } + public final void pshufd(Register dst, Register src, int imm8) { assert isUByte(imm8) : "invalid value"; assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM); @@ -3322,6 +3350,13 @@ public class AMD64Assembler extends Assembler { } } + public final void movdl(Register dst, AMD64Address src) { + AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target); + simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes); + emitByte(0x6E); + emitOperandHelper(dst, src, 0); + } + public final void movddup(Register dst, Register src) { assert supports(CPUFeature.SSE3); assert dst.getRegisterCategory().equals(AMD64.XMM); @@ -3457,6 +3492,14 @@ public class AMD64Assembler extends Assembler { emitByte(0xC0 | encode); } + public final void btrq(Register src, int imm8) { + int encode = prefixqAndEncode(src.encoding); + emitByte(0x0F); + emitByte(0xBA); + emitByte(0xF0 | encode); + emitByte(imm8); + } + public final void xaddl(AMD64Address dst, Register src) { prefix(dst, src); emitByte(0x0F); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java index fc4f7e74edc..36995bf6853 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java @@ -22,11 +22,17 @@ */ package org.graalvm.compiler.asm.amd64; +import static jdk.vm.ci.amd64.AMD64.rax; +import static jdk.vm.ci.amd64.AMD64.rcx; +import static jdk.vm.ci.amd64.AMD64.rdx; +import static jdk.vm.ci.amd64.AMD64.rsp; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseIncDec; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmLoadAndClearUpper; import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmRegToRegMoveAll; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.asm.Label; +import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64Kind; @@ -138,6 +144,10 @@ public class AMD64MacroAssembler extends AMD64Assembler { cmpq(src1, src2); } + public final void decrementl(Register reg) { + decrementl(reg, 1); + } + public final void decrementl(Register reg, int value) { if (value == Integer.MIN_VALUE) { subl(reg, value); @@ -321,4 +331,434 @@ public class AMD64MacroAssembler extends AMD64Assembler { movdbl(dest, tmp); addq(AMD64.rsp, AMD64Kind.DOUBLE.getSizeInBytes()); } + + // IndexOf for constant substrings with size >= 8 chars + // which don't need to be loaded through stack. + public void stringIndexofC8(Register str1, Register str2, + Register cnt1, Register cnt2, + int intCnt2, Register result, + Register vec, Register tmp) { + // assert(UseSSE42Intrinsics, "SSE4.2 is required"); + + // This method uses pcmpestri inxtruction with bound registers + // inputs: + // xmm - substring + // rax - substring length (elements count) + // mem - scanned string + // rdx - string length (elements count) + // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) + // outputs: + // rcx - matched index in string + assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri"; + + Label reloadSubstr = new Label(); + Label scanToSubstr = new Label(); + Label scanSubstr = new Label(); + Label retFound = new Label(); + Label retNotFound = new Label(); + Label exit = new Label(); + Label foundSubstr = new Label(); + Label matchSubstrHead = new Label(); + Label reloadStr = new Label(); + Label foundCandidate = new Label(); + + // Note, inline_string_indexOf() generates checks: + // if (substr.count > string.count) return -1; + // if (substr.count == 0) return 0; + assert intCnt2 >= 8 : "this code isused only for cnt2 >= 8 chars"; + + // Load substring. + movdqu(vec, new AMD64Address(str2, 0)); + movl(cnt2, intCnt2); + movq(result, str1); // string addr + + if (intCnt2 > 8) { + jmpb(scanToSubstr); + + // Reload substr for rescan, this code + // is executed only for large substrings (> 8 chars) + bind(reloadSubstr); + movdqu(vec, new AMD64Address(str2, 0)); + negq(cnt2); // Jumped here with negative cnt2, convert to positive + + bind(reloadStr); + // We came here after the beginning of the substring was + // matched but the rest of it was not so we need to search + // again. Start from the next element after the previous match. + + // cnt2 is number of substring reminding elements and + // cnt1 is number of string reminding elements when cmp failed. + // Restored cnt1 = cnt1 - cnt2 + int_cnt2 + subl(cnt1, cnt2); + addl(cnt1, intCnt2); + movl(cnt2, intCnt2); // Now restore cnt2 + + decrementl(cnt1, 1); // Shift to next element + cmpl(cnt1, cnt2); + jccb(ConditionFlag.Negative, retNotFound); // Left less then substring + + addq(result, 2); + + } // (int_cnt2 > 8) + + // Scan string for start of substr in 16-byte vectors + bind(scanToSubstr); + pcmpestri(vec, new AMD64Address(result, 0), 0x0d); + jccb(ConditionFlag.Below, foundCandidate); // CF == 1 + subl(cnt1, 8); + jccb(ConditionFlag.LessEqual, retNotFound); // Scanned full string + cmpl(cnt1, cnt2); + jccb(ConditionFlag.Negative, retNotFound); // Left less then substring + addq(result, 16); + jmpb(scanToSubstr); + + // Found a potential substr + bind(foundCandidate); + // Matched whole vector if first element matched (tmp(rcx) == 0). + if (intCnt2 == 8) { + jccb(ConditionFlag.Overflow, retFound); // OF == 1 + } else { // int_cnt2 > 8 + jccb(ConditionFlag.Overflow, foundSubstr); + } + // After pcmpestri tmp(rcx) contains matched element index + // Compute start addr of substr + leaq(result, new AMD64Address(result, tmp, Scale.Times2, 0)); + + // Make sure string is still long enough + subl(cnt1, tmp); + cmpl(cnt1, cnt2); + if (intCnt2 == 8) { + jccb(ConditionFlag.GreaterEqual, scanToSubstr); + } else { // int_cnt2 > 8 + jccb(ConditionFlag.GreaterEqual, matchSubstrHead); + } + // Left less then substring. + + bind(retNotFound); + movl(result, -1); + jmpb(exit); + + if (intCnt2 > 8) { + // This code is optimized for the case when whole substring + // is matched if its head is matched. + bind(matchSubstrHead); + pcmpestri(vec, new AMD64Address(result, 0), 0x0d); + // Reload only string if does not match + jccb(ConditionFlag.NoOverflow, reloadStr); // OF == 0 + + Label contScanSubstr = new Label(); + // Compare the rest of substring (> 8 chars). + bind(foundSubstr); + // First 8 chars are already matched. + negq(cnt2); + addq(cnt2, 8); + + bind(scanSubstr); + subl(cnt1, 8); + cmpl(cnt2, -8); // Do not read beyond substring + jccb(ConditionFlag.LessEqual, contScanSubstr); + // Back-up strings to avoid reading beyond substring: + // cnt1 = cnt1 - cnt2 + 8 + addl(cnt1, cnt2); // cnt2 is negative + addl(cnt1, 8); + movl(cnt2, 8); + negq(cnt2); + bind(contScanSubstr); + if (intCnt2 < 1024 * 1024 * 1024) { + movdqu(vec, new AMD64Address(str2, cnt2, Scale.Times2, intCnt2 * 2)); + pcmpestri(vec, new AMD64Address(result, cnt2, Scale.Times2, intCnt2 * 2), 0x0d); + } else { + // calculate index in register to avoid integer overflow (int_cnt2*2) + movl(tmp, intCnt2); + addq(tmp, cnt2); + movdqu(vec, new AMD64Address(str2, tmp, Scale.Times2, 0)); + pcmpestri(vec, new AMD64Address(result, tmp, Scale.Times2, 0), 0x0d); + } + // Need to reload strings pointers if not matched whole vector + jcc(ConditionFlag.NoOverflow, reloadSubstr); // OF == 0 + addq(cnt2, 8); + jcc(ConditionFlag.Negative, scanSubstr); + // Fall through if found full substring + + } // (int_cnt2 > 8) + + bind(retFound); + // Found result if we matched full small substring. + // Compute substr offset + subq(result, str1); + shrl(result, 1); // index + bind(exit); + + } // string_indexofC8 + + // Small strings are loaded through stack if they cross page boundary. + public void stringIndexOf(Register str1, Register str2, + Register cnt1, Register cnt2, + int intCnt2, Register result, + Register vec, Register tmp, int vmPageSize) { + // + // int_cnt2 is length of small (< 8 chars) constant substring + // or (-1) for non constant substring in which case its length + // is in cnt2 register. + // + // Note, inline_string_indexOf() generates checks: + // if (substr.count > string.count) return -1; + // if (substr.count == 0) return 0; + // + assert intCnt2 == -1 || (0 < intCnt2 && intCnt2 < 8) : "should be != 0"; + + // This method uses pcmpestri instruction with bound registers + // inputs: + // xmm - substring + // rax - substring length (elements count) + // mem - scanned string + // rdx - string length (elements count) + // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts) + // outputs: + // rcx - matched index in string + assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri"; + + Label reloadSubstr = new Label(); + Label scanToSubstr = new Label(); + Label scanSubstr = new Label(); + Label adjustStr = new Label(); + Label retFound = new Label(); + Label retNotFound = new Label(); + Label cleanup = new Label(); + Label foundSubstr = new Label(); + Label foundCandidate = new Label(); + + int wordSize = 8; + // We don't know where these strings are located + // and we can't read beyond them. Load them through stack. + Label bigStrings = new Label(); + Label checkStr = new Label(); + Label copySubstr = new Label(); + Label copyStr = new Label(); + + movq(tmp, rsp); // save old SP + + if (intCnt2 > 0) { // small (< 8 chars) constant substring + if (intCnt2 == 1) { // One char + movzwl(result, new AMD64Address(str2, 0)); + movdl(vec, result); // move 32 bits + } else if (intCnt2 == 2) { // Two chars + movdl(vec, new AMD64Address(str2, 0)); // move 32 bits + } else if (intCnt2 == 4) { // Four chars + movq(vec, new AMD64Address(str2, 0)); // move 64 bits + } else { // cnt2 = { 3, 5, 6, 7 } + // Array header size is 12 bytes in 32-bit VM + // + 6 bytes for 3 chars == 18 bytes, + // enough space to load vec and shift. + movdqu(vec, new AMD64Address(str2, (intCnt2 * 2) - 16)); + psrldq(vec, 16 - (intCnt2 * 2)); + } + } else { // not constant substring + cmpl(cnt2, 8); + jccb(ConditionFlag.AboveEqual, bigStrings); // Both strings are big enough + + // We can read beyond string if str+16 does not cross page boundary + // since heaps are aligned and mapped by pages. + assert vmPageSize < 1024 * 1024 * 1024 : "default page should be small"; + movl(result, str2); // We need only low 32 bits + andl(result, (vmPageSize - 1)); + cmpl(result, (vmPageSize - 16)); + jccb(ConditionFlag.BelowEqual, checkStr); + + // Move small strings to stack to allow load 16 bytes into vec. + subq(rsp, 16); + int stackOffset = wordSize - 2; + push(cnt2); + + bind(copySubstr); + movzwl(result, new AMD64Address(str2, cnt2, Scale.Times2, -2)); + movw(new AMD64Address(rsp, cnt2, Scale.Times2, stackOffset), result); + decrementl(cnt2, 1); + jccb(ConditionFlag.NotZero, copySubstr); + + pop(cnt2); + movq(str2, rsp); // New substring address + } // non constant + + bind(checkStr); + cmpl(cnt1, 8); + jccb(ConditionFlag.AboveEqual, bigStrings); + + // Check cross page boundary. + movl(result, str1); // We need only low 32 bits + andl(result, (vmPageSize - 1)); + cmpl(result, (vmPageSize - 16)); + jccb(ConditionFlag.BelowEqual, bigStrings); + + subq(rsp, 16); + int stackOffset = -2; + if (intCnt2 < 0) { // not constant + push(cnt2); + stackOffset += wordSize; + } + movl(cnt2, cnt1); + + bind(copyStr); + movzwl(result, new AMD64Address(str1, cnt2, Scale.Times2, -2)); + movw(new AMD64Address(rsp, cnt2, Scale.Times2, stackOffset), result); + decrementl(cnt2, 1); + jccb(ConditionFlag.NotZero, copyStr); + + if (intCnt2 < 0) { // not constant + pop(cnt2); + } + movq(str1, rsp); // New string address + + bind(bigStrings); + // Load substring. + if (intCnt2 < 0) { // -1 + movdqu(vec, new AMD64Address(str2, 0)); + push(cnt2); // substr count + push(str2); // substr addr + push(str1); // string addr + } else { + // Small (< 8 chars) constant substrings are loaded already. + movl(cnt2, intCnt2); + } + push(tmp); // original SP + // Finished loading + + // ======================================================== + // Start search + // + + movq(result, str1); // string addr + + if (intCnt2 < 0) { // Only for non constant substring + jmpb(scanToSubstr); + + // SP saved at sp+0 + // String saved at sp+1*wordSize + // Substr saved at sp+2*wordSize + // Substr count saved at sp+3*wordSize + + // Reload substr for rescan, this code + // is executed only for large substrings (> 8 chars) + bind(reloadSubstr); + movq(str2, new AMD64Address(rsp, 2 * wordSize)); + movl(cnt2, new AMD64Address(rsp, 3 * wordSize)); + movdqu(vec, new AMD64Address(str2, 0)); + // We came here after the beginning of the substring was + // matched but the rest of it was not so we need to search + // again. Start from the next element after the previous match. + subq(str1, result); // Restore counter + shrl(str1, 1); + addl(cnt1, str1); + decrementl(cnt1); // Shift to next element + cmpl(cnt1, cnt2); + jccb(ConditionFlag.Negative, retNotFound); // Left less then substring + + addq(result, 2); + } // non constant + + // Scan string for start of substr in 16-byte vectors + bind(scanToSubstr); + assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri"; + pcmpestri(vec, new AMD64Address(result, 0), 0x0d); + jccb(ConditionFlag.Below, foundCandidate); // CF == 1 + subl(cnt1, 8); + jccb(ConditionFlag.LessEqual, retNotFound); // Scanned full string + cmpl(cnt1, cnt2); + jccb(ConditionFlag.Negative, retNotFound); // Left less then substring + addq(result, 16); + + bind(adjustStr); + cmpl(cnt1, 8); // Do not read beyond string + jccb(ConditionFlag.GreaterEqual, scanToSubstr); + // Back-up string to avoid reading beyond string. + leaq(result, new AMD64Address(result, cnt1, Scale.Times2, -16)); + movl(cnt1, 8); + jmpb(scanToSubstr); + + // Found a potential substr + bind(foundCandidate); + // After pcmpestri tmp(rcx) contains matched element index + + // Make sure string is still long enough + subl(cnt1, tmp); + cmpl(cnt1, cnt2); + jccb(ConditionFlag.GreaterEqual, foundSubstr); + // Left less then substring. + + bind(retNotFound); + movl(result, -1); + jmpb(cleanup); + + bind(foundSubstr); + // Compute start addr of substr + leaq(result, new AMD64Address(result, tmp, Scale.Times2)); + + if (intCnt2 > 0) { // Constant substring + // Repeat search for small substring (< 8 chars) + // from new point without reloading substring. + // Have to check that we don't read beyond string. + cmpl(tmp, 8 - intCnt2); + jccb(ConditionFlag.Greater, adjustStr); + // Fall through if matched whole substring. + } else { // non constant + assert intCnt2 == -1 : "should be != 0"; + + addl(tmp, cnt2); + // Found result if we matched whole substring. + cmpl(tmp, 8); + jccb(ConditionFlag.LessEqual, retFound); + + // Repeat search for small substring (<= 8 chars) + // from new point 'str1' without reloading substring. + cmpl(cnt2, 8); + // Have to check that we don't read beyond string. + jccb(ConditionFlag.LessEqual, adjustStr); + + Label checkNext = new Label(); + Label contScanSubstr = new Label(); + Label retFoundLong = new Label(); + // Compare the rest of substring (> 8 chars). + movq(str1, result); + + cmpl(tmp, cnt2); + // First 8 chars are already matched. + jccb(ConditionFlag.Equal, checkNext); + + bind(scanSubstr); + pcmpestri(vec, new AMD64Address(str1, 0), 0x0d); + // Need to reload strings pointers if not matched whole vector + jcc(ConditionFlag.NoOverflow, reloadSubstr); // OF == 0 + + bind(checkNext); + subl(cnt2, 8); + jccb(ConditionFlag.LessEqual, retFoundLong); // Found full substring + addq(str1, 16); + addq(str2, 16); + subl(cnt1, 8); + cmpl(cnt2, 8); // Do not read beyond substring + jccb(ConditionFlag.GreaterEqual, contScanSubstr); + // Back-up strings to avoid reading beyond substring. + leaq(str2, new AMD64Address(str2, cnt2, Scale.Times2, -16)); + leaq(str1, new AMD64Address(str1, cnt2, Scale.Times2, -16)); + subl(cnt1, cnt2); + movl(cnt2, 8); + addl(cnt1, 8); + bind(contScanSubstr); + movdqu(vec, new AMD64Address(str2, 0)); + jmpb(scanSubstr); + + bind(retFoundLong); + movq(str1, new AMD64Address(rsp, wordSize)); + } // non constant + + bind(retFound); + // Compute substr offset + subq(result, str1); + shrl(result, 1); // index + + bind(cleanup); + pop(rsp); // restore SP + + } + } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java index 68cde9dcfdf..582247c4d72 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2017, 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 @@ -135,8 +135,8 @@ import java.util.Map; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.code.Register; @@ -1757,6 +1757,10 @@ public abstract class SPARCAssembler extends Assembler { return constant.isNull() || isSimm(constant.asLong(), 5); } + public static boolean isSimm5(long imm) { + return isSimm(imm, 5); + } + public static boolean isSimm13(int imm) { return isSimm(imm, 13); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCMacroAssembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCMacroAssembler.java index 47615118361..59ef7ff2c16 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCMacroAssembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCMacroAssembler.java @@ -81,6 +81,10 @@ public class SPARCMacroAssembler extends SPARCAssembler { nop(); // delay slot } + public void bz(Label l) { + BPCC.emit(this, Xcc, ConditionFlag.Zero, NOT_ANNUL, PREDICT_NOT_TAKEN, l); + } + @Override protected final void patchJumpTarget(int branch, int branchTarget) { final int disp = (branchTarget - branch) / 4; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java index a7c1fb03087..8eb113cc175 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java @@ -26,20 +26,18 @@ import static org.graalvm.compiler.core.common.CompilationRequestIdentifier.asCo import java.lang.reflect.Method; -import org.junit.Assert; - import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.code.DisassemblerProvider; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.compiler.serviceprovider.GraalServices; import org.graalvm.compiler.test.GraalTest; +import org.junit.Assert; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.CodeCacheProvider; @@ -62,6 +60,14 @@ public abstract class AssemblerTest extends GraalTest { byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc); } + /** + * Gets the initial option values provided by the Graal runtime. These are option values + * typically parsed from the command line. + */ + public static OptionValues getInitialOptions() { + return Graal.getRequiredCapability(OptionValues.class); + } + public AssemblerTest() { JVMCIBackend providers = JVMCI.getRuntime().getHostJVMCIBackend(); this.metaAccess = providers.getMetaAccess(); @@ -76,10 +82,13 @@ public abstract class AssemblerTest extends GraalTest { @SuppressWarnings("try") protected InstalledCode assembleMethod(Method m, CodeGenTest test) { ResolvedJavaMethod method = getMetaAccess().lookupJavaMethod(m); - try (Scope s = Debug.scope("assembleMethod", method, codeCache)) { + OptionValues options = getInitialOptions(); + DebugContext debug = getDebugContext(options); + try (DebugContext.Scope s = debug.scope("assembleMethod", method, codeCache)) { RegisterConfig registerConfig = codeCache.getRegisterConfig(); CompilationIdentifier compilationId = backend.getCompilationIdentifier(method); - CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, new StructuredGraph(method, AllowAssumptions.NO, compilationId), null).getCallingConvention(); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).compilationId(compilationId).build(); + CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, graph, null).getCallingConvention(); CompilationResult compResult = new CompilationResult(); byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc); @@ -87,7 +96,7 @@ public abstract class AssemblerTest extends GraalTest { compResult.setTotalFrameSize(0); compResult.close(); - InstalledCode code = backend.addInstalledCode(method, asCompilationRequest(compilationId), compResult); + InstalledCode code = backend.addInstalledCode(debug, method, asCompilationRequest(compilationId), compResult); for (DisassemblerProvider dis : GraalServices.load(DisassemblerProvider.class)) { String disasm1 = dis.disassembleCompiledCode(codeCache, compResult); @@ -97,7 +106,7 @@ public abstract class AssemblerTest extends GraalTest { } return code; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java index d6df78393ea..4d8c3ea1cbb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.asm; +import org.graalvm.compiler.core.common.NumUtil; + import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Arrays; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/Bytecode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/Bytecode.java index 60f0b5203d1..59b791bdb4e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/Bytecode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/Bytecode.java @@ -63,6 +63,11 @@ public interface Bytecode { ExceptionHandler[] getExceptionHandlers(); + /** + * Gets the {@link BytecodeProvider} from which this object was acquired. + */ + BytecodeProvider getOrigin(); + static String toLocation(Bytecode bytecode, int bci) { return appendLocation(new StringBuilder(), bytecode, bci).toString(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/BytecodeDisassembler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/BytecodeDisassembler.java index c295daeb259..41e52e24482 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/BytecodeDisassembler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/BytecodeDisassembler.java @@ -165,7 +165,7 @@ public class BytecodeDisassembler { stream.next(); opcode = stream.currentBC(); } - } catch (RuntimeException e) { + } catch (Throwable e) { throw new RuntimeException(String.format("Error disassembling %s%nPartial disassembly:%n%s", method.format("%H.%n(%p)"), buf.toString()), e); } return buf.toString(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecode.java index 39b6e83f65b..ee9c81278f7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecode.java @@ -36,9 +36,20 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class ResolvedJavaMethodBytecode implements Bytecode { private final ResolvedJavaMethod method; + private final BytecodeProvider origin; public ResolvedJavaMethodBytecode(ResolvedJavaMethod method) { + this(method, ResolvedJavaMethodBytecodeProvider.INSTANCE); + } + + public ResolvedJavaMethodBytecode(ResolvedJavaMethod method, BytecodeProvider origin) { this.method = method; + this.origin = origin; + } + + @Override + public BytecodeProvider getOrigin() { + return origin; } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecodeProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecodeProvider.java index b2f0409a3ba..a4b3149bac5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecodeProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.bytecode/src/org/graalvm/compiler/bytecode/ResolvedJavaMethodBytecodeProvider.java @@ -29,9 +29,14 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; */ public class ResolvedJavaMethodBytecodeProvider implements BytecodeProvider { + /** + * A state-less, shared {@link ResolvedJavaMethodBytecodeProvider} instance. + */ + public static final ResolvedJavaMethodBytecodeProvider INSTANCE = new ResolvedJavaMethodBytecodeProvider(); + @Override public Bytecode getBytecode(ResolvedJavaMethod method) { - return new ResolvedJavaMethodBytecode(method); + return new ResolvedJavaMethodBytecode(method, this); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java index ba1267bca4b..4c7bfafaff9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java @@ -34,6 +34,7 @@ import java.util.List; import java.util.Objects; import org.graalvm.compiler.graph.NodeSourcePosition; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.DebugInfo; import jdk.vm.ci.code.StackSlot; @@ -299,7 +300,6 @@ public class CompilationResult { * Sets the assumptions made during compilation. */ public void setAssumptions(Assumption[] assumptions) { - checkOpen(); this.assumptions = assumptions; } @@ -363,9 +363,10 @@ public class CompilationResult { * * @param accessedFields the collected set of fields accessed during compilation */ - public void setFields(Collection accessedFields) { - assert accessedFields != null; - fields = accessedFields.toArray(new ResolvedJavaField[accessedFields.size()]); + public void setFields(EconomicSet accessedFields) { + if (accessedFields != null) { + fields = accessedFields.toArray(new ResolvedJavaField[accessedFields.size()]); + } } /** diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java index d28ab09afd2..96570b3cb09 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.code; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; /** * Represents a bailout exception with a stack trace in terms of the Java source being compiled diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLoweringByUse.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLoweringByUse.java new file mode 100644 index 00000000000..f584d35d65a --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLoweringByUse.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.graalvm.compiler.core.aarch64; + +import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.meta.JavaConstant; +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.AddNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; +import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; +import org.graalvm.compiler.nodes.memory.address.RawAddressNode; +import org.graalvm.compiler.phases.common.AddressLoweringByUsePhase; + +public class AArch64AddressLoweringByUse extends AddressLoweringByUsePhase.AddressLoweringByUse { + private AArch64LIRKindTool kindtool; + + public AArch64AddressLoweringByUse(AArch64LIRKindTool kindtool) { + this.kindtool = kindtool; + } + + @Override + public AddressNode lower(ValueNode use, Stamp stamp, AddressNode address) { + if (address instanceof RawAddressNode) { + return doLower(stamp, address.getBase(), null); + } else if (address instanceof OffsetAddressNode) { + OffsetAddressNode offsetAddress = (OffsetAddressNode) address; + return doLower(stamp, offsetAddress.getBase(), offsetAddress.getOffset()); + } else { + // must be an already transformed AArch64AddressNode + return address; + } + } + + @Override + public AddressNode lower(AddressNode address) { + return lower(null, null, address); + } + + private AddressNode doLower(Stamp stamp, ValueNode base, ValueNode index) { + AArch64AddressNode ret = new AArch64AddressNode(base, index); + AArch64Kind aarch64Kind = (stamp == null ? null : getAArch64Kind(stamp)); + + // improve the address as much as possible + boolean changed; + do { + changed = improve(aarch64Kind, ret); + } while (changed); + + // avoid duplicates + return base.graph().unique(ret); + } + + protected boolean improve(AArch64Kind kind, AArch64AddressNode ret) { + AArch64Address.AddressingMode mode = ret.getAddressingMode(); + // if we have already set a displacement or set to base only mode then we are done + if (isDisplacementMode(mode) || isBaseOnlyMode(mode)) { + return false; + } + ValueNode base = ret.getBase(); + ValueNode index = ret.getIndex(); + + // avoid a constant or null base if possible + if (base == null) { + ret.setBase(index); + ret.setIndex(base); + return true; + } + // make sure any integral JavaConstant + // is the index rather than the base + // strictly we don't need the conditions on index + // as we ought not to see two JavaConstant values + if (base.isJavaConstant() && base.asJavaConstant().getJavaKind().isNumericInteger() && + index != null && !index.isJavaConstant()) { + ret.setBase(index); + ret.setIndex(base); + return true; + } + + // if the base is an add then move it up + if (index == null && base instanceof AddNode) { + AddNode add = (AddNode) base; + ret.setBase(add.getX()); + ret.setIndex(add.getY()); + return true; + } + + // we can try to fold a JavaConstant index into a displacement + if (index != null && index.isJavaConstant()) { + JavaConstant javaConstant = index.asJavaConstant(); + if (javaConstant.getJavaKind().isNumericInteger()) { + long disp = javaConstant.asLong(); + mode = immediateMode(kind, disp); + if (isDisplacementMode(mode)) { + index = null; + // we can fold this in as a displacement + // but first see if we can pull up any additional + // constants added into the base + boolean tryNextBase = (base instanceof AddNode); + while (tryNextBase) { + AddNode add = (AddNode) base; + tryNextBase = false; + ValueNode child = add.getX(); + if (child.isJavaConstant() && child.asJavaConstant().getJavaKind().isNumericInteger()) { + long newDisp = disp + child.asJavaConstant().asLong(); + AArch64Address.AddressingMode newMode = immediateMode(kind, newDisp); + if (newMode != AArch64Address.AddressingMode.REGISTER_OFFSET) { + disp = newDisp; + mode = newMode; + base = add.getY(); + ret.setBase(base); + tryNextBase = (base instanceof AddNode); + } + } else { + child = add.getY(); + if (child.isJavaConstant() && child.asJavaConstant().getJavaKind().isNumericInteger()) { + long newDisp = disp + child.asJavaConstant().asLong(); + AArch64Address.AddressingMode newMode = immediateMode(kind, newDisp); + if (newMode != AArch64Address.AddressingMode.REGISTER_OFFSET) { + disp = newDisp; + mode = newMode; + base = add.getX(); + ret.setBase(base); + tryNextBase = (base instanceof AddNode); + } + } + } + } + if (disp != 0) { + // ok now set the displacement in place of an index + ret.setIndex(null); + int scaleFactor = computeScaleFactor(kind, mode); + ret.setDisplacement(disp, scaleFactor, mode); + } else { + // reset to base register only + ret.setIndex(null); + ret.setDisplacement(0, 1, AArch64Address.AddressingMode.BASE_REGISTER_ONLY); + } + return true; + } + } + } + // nope cannot improve this any more + return false; + } + + private AArch64Kind getAArch64Kind(Stamp stamp) { + LIRKind lirKind = stamp.getLIRKind(kindtool); + if (!lirKind.isValue()) { + if (!lirKind.isReference(0) || lirKind.getReferenceCount() != 1) { + return null; + } + } + + return (AArch64Kind) lirKind.getPlatformKind(); + } + + private static AArch64Address.AddressingMode immediateMode(AArch64Kind kind, long value) { + if (kind != null) { + int size = kind.getSizeInBytes(); + // this next test should never really fail + if ((value & (size - 1)) == 0) { + long encodedValue = value / size; + // assert value % size == 0 + // we can try for a 12 bit scaled offset + if (NumUtil.isUnsignedNbit(12, encodedValue)) { + return AArch64Address.AddressingMode.IMMEDIATE_SCALED; + } + } + } + + // we can try for a 9 bit unscaled offset + if (NumUtil.isSignedNbit(9, value)) { + return AArch64Address.AddressingMode.IMMEDIATE_UNSCALED; + } + + // nope this index needs to be passed via offset register + return AArch64Address.AddressingMode.REGISTER_OFFSET; + } + + private static int computeScaleFactor(AArch64Kind kind, AArch64Address.AddressingMode mode) { + if (mode == AArch64Address.AddressingMode.IMMEDIATE_SCALED) { + return kind.getSizeInBytes(); + } + return 1; + } + + boolean isBaseOnlyMode(AArch64Address.AddressingMode addressingMode) { + return addressingMode == AArch64Address.AddressingMode.BASE_REGISTER_ONLY; + } + + private static boolean isDisplacementMode(AArch64Address.AddressingMode addressingMode) { + switch (addressingMode) { + case IMMEDIATE_POST_INDEXED: + case IMMEDIATE_PRE_INDEXED: + case IMMEDIATE_SCALED: + case IMMEDIATE_UNSCALED: + return true; + } + return false; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java index 176480dd2a5..3fddb853424 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java @@ -26,7 +26,6 @@ package org.graalvm.compiler.core.aarch64; import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; @@ -40,7 +39,7 @@ import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Value; /** - * Represents an address of the form... TODO. + * Represents an AArch64 address in the graph. */ @NodeInfo public class AArch64AddressNode extends AddressNode implements LIRLowerable { @@ -52,7 +51,8 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { @OptionalInput private ValueNode index; private AArch64Address.AddressingMode addressingMode; - private int displacement; + private long displacement; + private int scaleFactor; public AArch64AddressNode(ValueNode base) { this(base, null); @@ -63,6 +63,8 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { this.base = base; this.index = index; this.addressingMode = AddressingMode.REGISTER_OFFSET; + this.displacement = 0; + this.scaleFactor = 1; } @Override @@ -74,9 +76,10 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { AllocatableValue baseReference = LIRKind.derivedBaseFromValue(baseValue); AllocatableValue indexReference; - if (addressingMode.equals(AddressingMode.IMMEDIATE_UNSCALED)) { + if (index == null) { + indexReference = null; + } else if (addressingMode.equals(AddressingMode.IMMEDIATE_UNSCALED)) { indexReference = LIRKind.derivedBaseFromValue(indexValue); - throw GraalError.unimplemented(); } else { if (LIRKind.isValue(indexValue.getValueKind())) { indexReference = null; @@ -86,10 +89,10 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { } LIRKind kind = LIRKind.combineDerived(tool.getLIRKind(stamp()), baseReference, indexReference); - final boolean scaled = false; - gen.setResult(this, new AArch64AddressValue(kind, baseValue, indexValue, displacement, scaled, addressingMode)); + gen.setResult(this, new AArch64AddressValue(kind, baseValue, indexValue, (int) displacement, scaleFactor, addressingMode)); } + @Override public ValueNode getBase() { return base; } @@ -102,6 +105,7 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { this.base = base; } + @Override public ValueNode getIndex() { return index; } @@ -114,11 +118,22 @@ public class AArch64AddressNode extends AddressNode implements LIRLowerable { this.index = index; } - public int getDisplacement() { + public long getDisplacement() { return displacement; } - public void setDisplacement(int displacement) { + public void setDisplacement(long displacement, int scaleFactor, AArch64Address.AddressingMode addressingMode) { this.displacement = displacement; + this.scaleFactor = scaleFactor; + this.addressingMode = addressingMode; + } + + @Override + public long getMaxConstantDisplacement() { + return displacement; + } + + public AddressingMode getAddressingMode() { + return addressingMode; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java index 786b6692aa6..b17843f37e2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java @@ -23,13 +23,16 @@ package org.graalvm.compiler.core.aarch64; -import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; -import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static jdk.vm.ci.aarch64.AArch64.sp; import static jdk.vm.ci.aarch64.AArch64Kind.DWORD; import static jdk.vm.ci.aarch64.AArch64Kind.QWORD; +import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; +import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; +import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.BSR; +import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CLZ; +import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CTZ; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.FloatConvert; @@ -41,12 +44,12 @@ import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool; import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp; import org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp; -import org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode; import org.graalvm.compiler.lir.aarch64.AArch64Move.LoadOp; import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreConstantOp; import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp; import org.graalvm.compiler.lir.aarch64.AArch64ReinterpretOp; import org.graalvm.compiler.lir.aarch64.AArch64SignExtendOp; +import org.graalvm.compiler.lir.aarch64.AArch64Unary; import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator; import jdk.vm.ci.aarch64.AArch64Kind; @@ -91,11 +94,30 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem } } + public Value emitExtendMemory(boolean isSigned, AArch64Kind memoryKind, int resultBits, AArch64AddressValue address, LIRFrameState state) { + // Issue a zero extending load of the proper bit size and set the result to + // the proper kind. + Variable result = getLIRGen().newVariable(LIRKind.value(resultBits == 32 ? AArch64Kind.DWORD : AArch64Kind.QWORD)); + + int targetSize = resultBits <= 32 ? 32 : 64; + switch (memoryKind) { + case BYTE: + case WORD: + case DWORD: + case QWORD: + getLIRGen().append(new AArch64Unary.MemoryOp(isSigned, targetSize, + memoryKind.getSizeInBytes() * 8, result, address, state)); + break; + default: + throw GraalError.shouldNotReachHere(); + } + return result; + } + @Override public Value emitMul(Value a, Value b, boolean setFlags) { - // TODO (das) setFlags handling - should be handled higher up. Ask for ideas at mailing list - assert !setFlags : "Set flags on multiplication is not supported"; - return emitBinary(LIRKind.combine(a, b), getOpCode(a, AArch64ArithmeticOp.MUL, AArch64ArithmeticOp.FMUL), true, a, b); + AArch64ArithmeticOp intOp = setFlags ? AArch64ArithmeticOp.MULVS : AArch64ArithmeticOp.MUL; + return emitBinary(LIRKind.combine(a, b), getOpCode(a, intOp, AArch64ArithmeticOp.FMUL), true, a, b); } @Override @@ -223,7 +245,7 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem @Override public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) { - assert fromBits <= toBits && (toBits == 32 || toBits == 64); + assert fromBits <= toBits && toBits <= 64; if (fromBits == toBits) { return inputVal; } @@ -235,11 +257,21 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem @Override public Value emitSignExtend(Value inputVal, int fromBits, int toBits) { - assert fromBits <= toBits && (toBits == 32 || toBits == 64); + LIRKind resultKind = getResultLirKind(toBits, inputVal); + assert fromBits <= toBits && toBits <= 64; if (fromBits == toBits) { return inputVal; + } else if (isJavaConstant(inputVal)) { + JavaConstant javaConstant = asJavaConstant(inputVal); + long constant; + if (javaConstant.isNull()) { + constant = 0; + } else { + constant = javaConstant.asLong(); + } + int shiftCount = QWORD.getSizeInBytes() * 8 - fromBits; + return new ConstantValue(resultKind, JavaConstant.forLong((constant << shiftCount) >> shiftCount)); } - LIRKind resultKind = getResultLirKind(toBits, inputVal); Variable result = getLIRGen().newVariable(resultKind); getLIRGen().append(new AArch64SignExtendOp(result, getLIRGen().asAllocatable(inputVal), fromBits, toBits)); return result; @@ -249,7 +281,8 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem if (resultBitSize == 64) { return LIRKind.combine(inputValues).changeType(QWORD); } else { - assert resultBitSize == 32; + // FIXME: I have no idea what this assert was ever for + // assert resultBitSize == 32; return LIRKind.combine(inputValues).changeType(DWORD); } } @@ -352,8 +385,8 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem } @Override - public Value emitBitScanForward(Value inputVal) { - return emitBitManipulation(AArch64BitManipulationOp.BitManipulationOpCode.BSF, inputVal); + public Variable emitBitScanForward(Value value) { + throw GraalError.unimplemented(); } @Override @@ -362,27 +395,23 @@ public class AArch64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implem } @Override - public Value emitBitScanReverse(Value inputVal) { - // TODO (das) old implementation said to use emitCountLeadingZeros instead - need extra node - // for that though - return emitBitManipulation(BitManipulationOpCode.BSR, inputVal); + public Value emitBitScanReverse(Value value) { + Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD)); + getLIRGen().append(new AArch64BitManipulationOp(BSR, result, getLIRGen().asAllocatable(value))); + return result; } @Override public Value emitCountLeadingZeros(Value value) { - return emitBitManipulation(BitManipulationOpCode.CLZ, value); + Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD)); + getLIRGen().append(new AArch64BitManipulationOp(CLZ, result, getLIRGen().asAllocatable(value))); + return result; } @Override public Value emitCountTrailingZeros(Value value) { - throw GraalError.unimplemented(); - } - - private Variable emitBitManipulation(AArch64BitManipulationOp.BitManipulationOpCode op, Value inputVal) { - assert isNumericInteger(inputVal.getPlatformKind()); - AllocatableValue input = getLIRGen().asAllocatable(inputVal); - Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - getLIRGen().append(new AArch64BitManipulationOp(op, result, input)); + Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD)); + getLIRGen().append(new AArch64BitManipulationOp(CTZ, result, getLIRGen().asAllocatable(value))); return result; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java index 03e777a2aa8..34a7a0872ea 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java @@ -42,11 +42,14 @@ import org.graalvm.compiler.lir.SwitchStrategy; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp; +import org.graalvm.compiler.lir.aarch64.AArch64ArrayEqualsOp; +import org.graalvm.compiler.lir.aarch64.AArch64ByteSwapOp; import org.graalvm.compiler.lir.aarch64.AArch64Compare; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.BranchOp; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CondMoveOp; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp; +import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.TableSwitchOp; import org.graalvm.compiler.lir.aarch64.AArch64Move; import org.graalvm.compiler.lir.aarch64.AArch64Move.CompareAndSwapOp; import org.graalvm.compiler.lir.aarch64.AArch64Move.MembarOp; @@ -56,6 +59,7 @@ import org.graalvm.compiler.lir.gen.LIRGenerator; import org.graalvm.compiler.phases.util.Providers; import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.RegisterValue; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.JavaConstant; @@ -116,13 +120,24 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { if (address instanceof AArch64AddressValue) { return (AArch64AddressValue) address; } else { - return new AArch64AddressValue(address.getValueKind(), asAllocatable(address), Value.ILLEGAL, 0, false, AddressingMode.BASE_REGISTER_ONLY); + return new AArch64AddressValue(address.getValueKind(), asAllocatable(address), Value.ILLEGAL, 0, 1, AddressingMode.BASE_REGISTER_ONLY); } } @Override - public Variable emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + public Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + Variable prevValue = newVariable(expectedValue.getValueKind()); + Variable scratch = newVariable(LIRKind.value(AArch64Kind.DWORD)); + append(new CompareAndSwapOp(prevValue, loadReg(expectedValue), loadReg(newValue), asAllocatable(address), scratch)); + assert trueValue.getValueKind().equals(falseValue.getValueKind()); Variable result = newVariable(trueValue.getValueKind()); + append(new CondMoveOp(result, ConditionFlag.EQ, asAllocatable(trueValue), asAllocatable(falseValue))); + return result; + } + + @Override + public Variable emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue) { + Variable result = newVariable(newValue.getValueKind()); Variable scratch = newVariable(LIRKind.value(AArch64Kind.WORD)); append(new CompareAndSwapOp(result, loadNonCompareConst(expectedValue), loadReg(newValue), asAllocatable(address), scratch)); return result; @@ -271,13 +286,25 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { boolean mirrored; AArch64Kind kind = (AArch64Kind) cmpKind; if (kind.isInteger()) { - if (LIRValueUtil.isVariable(b)) { - left = load(b); - right = loadNonConst(a); + Value aExt = a; + Value bExt = b; + + int compareBytes = cmpKind.getSizeInBytes(); + // AArch64 compares 32 or 64 bits: sign extend a and b as required. + if (compareBytes < a.getPlatformKind().getSizeInBytes()) { + aExt = arithmeticLIRGen.emitSignExtend(a, compareBytes * 8, 64); + } + if (compareBytes < b.getPlatformKind().getSizeInBytes()) { + bExt = arithmeticLIRGen.emitSignExtend(b, compareBytes * 8, 64); + } + + if (LIRValueUtil.isVariable(bExt)) { + left = load(bExt); + right = loadNonConst(aExt); mirrored = true; } else { - left = load(a); - right = loadNonConst(b); + left = load(aExt); + right = loadNonConst(bExt); mirrored = false; } append(new AArch64Compare.CompareOp(left, loadNonCompareConst(right))); @@ -367,7 +394,7 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) { assert ((AArch64Kind) left.getPlatformKind()).isInteger() && ((AArch64Kind) right.getPlatformKind()).isInteger(); assert ((AArch64Kind) trueValue.getPlatformKind()).isInteger() && ((AArch64Kind) falseValue.getPlatformKind()).isInteger(); - ((AArch64ArithmeticLIRGenerator) getArithmetic()).emitBinary(trueValue.getValueKind(), AArch64ArithmeticOp.ANDS, true, left, right); + ((AArch64ArithmeticLIRGenerator) getArithmetic()).emitBinary(left.getValueKind(), AArch64ArithmeticOp.ANDS, true, left, right); Variable result = newVariable(trueValue.getValueKind()); append(new CondMoveOp(result, ConditionFlag.EQ, load(trueValue), load(falseValue))); return result; @@ -385,22 +412,21 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { @Override protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) { - // Make copy of key since the TableSwitch destroys its input. - Variable tmp = emitMove(key); - Variable scratch = newVariable(LIRKind.value(AArch64Kind.WORD)); - append(new AArch64ControlFlow.TableSwitchOp(lowKey, defaultTarget, targets, tmp, scratch)); + append(new TableSwitchOp(lowKey, defaultTarget, targets, key, newVariable(LIRKind.value(target().arch.getWordKind())), newVariable(key.getValueKind()))); } @Override - public Variable emitByteSwap(Value operand) { - // TODO (das) Do not generate until we support vector instructions - throw GraalError.unimplemented("Do not generate until we support vector instructions"); + public Variable emitByteSwap(Value input) { + Variable result = newVariable(LIRKind.combine(input)); + append(new AArch64ByteSwapOp(result, input)); + return result; } @Override public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length) { - // TODO (das) Do not generate until we support vector instructions - throw GraalError.unimplemented("Do not generate until we support vector instructions"); + Variable result = newVariable(LIRKind.value(AArch64Kind.DWORD)); + append(new AArch64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length))); + return result; } @Override @@ -443,4 +469,6 @@ public abstract class AArch64LIRGenerator extends LIRGenerator { public void emitPause() { append(new AArch64PauseOp()); } + + public abstract void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRKindTool.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRKindTool.java index 101a59d96a8..71f55db33c5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRKindTool.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRKindTool.java @@ -66,4 +66,13 @@ public class AArch64LIRKindTool implements LIRKindTool { return LIRKind.value(AArch64Kind.QWORD); } + @Override + public LIRKind getNarrowOopKind() { + return LIRKind.reference(AArch64Kind.DWORD); + } + + @Override + public LIRKind getNarrowPointerKind() { + return LIRKind.value(AArch64Kind.DWORD); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java index fe042027b37..6fa9bbd63b2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java @@ -86,21 +86,30 @@ public class AArch64MoveFactory implements MoveFactory { } @Override - public boolean canInlineConstant(JavaConstant c) { - switch (c.getJavaKind()) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - return AArch64MacroAssembler.isMovableImmediate(c.asInt()); - case Long: - return AArch64MacroAssembler.isMovableImmediate(c.asLong()); - case Object: - return c.isNull(); - default: - return false; + public LIRInstruction createStackLoad(AllocatableValue result, Constant input) { + return createLoad(result, input); + } + + @Override + public boolean canInlineConstant(Constant con) { + if (con instanceof JavaConstant) { + JavaConstant c = (JavaConstant) con; + switch (c.getJavaKind()) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + return AArch64MacroAssembler.isMovableImmediate(c.asInt()); + case Long: + return AArch64MacroAssembler.isMovableImmediate(c.asLong()); + case Object: + return c.isNull(); + default: + return false; + } } + return false; } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java similarity index 85% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesProvider.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java index 4eadf9cfaa3..e8b9b02bb7a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java @@ -22,13 +22,13 @@ */ package org.graalvm.compiler.core.aarch64; -import org.graalvm.compiler.java.DefaultSuitesProvider; +import org.graalvm.compiler.java.DefaultSuitesCreator; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; -public class AArch64SuitesProvider extends DefaultSuitesProvider { +public class AArch64SuitesCreator extends DefaultSuitesCreator { - public AArch64SuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) { + public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) { super(compilerConfiguration, plugins); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java index 0904f9ce409..c95707da994 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java @@ -38,8 +38,8 @@ public class AMD64AllocatorTest extends AllocatorTest { @Before public void checkAMD64() { assumeTrue("skipping AMD64 specific test", getTarget().arch instanceof AMD64); - assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue() == null); - assumeTrue("TraceRA is set -> skip", !TraceRA.getValue()); + assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue(getInitialOptions()) == null); + assumeTrue("TraceRA is set -> skip", !TraceRA.getValue(getInitialOptions())); } @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/MatchRuleTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/MatchRuleTest.java index a1384c11e43..7a6c0505481 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/MatchRuleTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/MatchRuleTest.java @@ -24,22 +24,23 @@ package org.graalvm.compiler.core.amd64.test; import static org.junit.Assume.assumeTrue; -import org.junit.Before; -import org.junit.Test; - import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer.MemoryConstOp; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.jtt.LIRTest; import org.graalvm.compiler.lir.phases.LIRPhase; +import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Before; +import org.junit.Test; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.code.TargetDescription; public class MatchRuleTest extends LIRTest { - private static LIR lir; + private LIR lir; @Before public void checkAMD64() { @@ -54,13 +55,19 @@ public class MatchRuleTest extends LIRTest { } } + @Override + protected LIRSuites createLIRSuites(OptionValues options) { + LIRSuites suites = super.createLIRSuites(options); + suites.getPreAllocationOptimizationStage().appendPhase(new CheckPhase()); + return suites; + } + /** * Verifies, if the match rules in AMD64NodeMatchRules do work on the graphs by compiling and * checking if the expected LIR instruction show up. */ @Test public void test1() { - getLIRSuites().getPreAllocationOptimizationStage().appendPhase(new CheckPhase()); compile(getResolvedJavaMethod("test1Snippet"), null); boolean found = false; for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) { @@ -83,7 +90,7 @@ public class MatchRuleTest extends LIRTest { } } - public static class CheckPhase extends LIRPhase { + public class CheckPhase extends LIRPhase { @Override protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreAllocationOptimizationContext context) { lir = lirGenRes.getLIR(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java index a43d03467b1..6a827f8c1fa 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java @@ -25,9 +25,10 @@ package org.graalvm.compiler.core.amd64; import jdk.vm.ci.meta.JavaConstant; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.common.type.IntegerStamp; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.LeftShiftNode; @@ -47,12 +48,15 @@ public class AMD64AddressLowering extends AddressLowering { AMD64AddressNode ret = new AMD64AddressNode(base, offset); boolean changed; do { - changed = improve(ret); + changed = improve(base.getDebug(), ret); } while (changed); return base.graph().unique(ret); } - protected boolean improve(AMD64AddressNode ret) { + /** + * @param debug + */ + protected boolean improve(DebugContext debug, AMD64AddressNode ret) { ValueNode newBase = improveInput(ret, ret.getBase(), 0); if (newBase != ret.getBase()) { ret.setBase(newBase); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java index 1281418aece..90a8258d41c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java @@ -26,10 +26,16 @@ package org.graalvm.compiler.core.amd64; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.spi.Simplifiable; +import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.lir.amd64.AMD64AddressValue; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.PhiNode; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -42,7 +48,7 @@ import jdk.vm.ci.meta.Value; * optional. */ @NodeInfo -public class AMD64AddressNode extends AddressNode implements LIRLowerable { +public class AMD64AddressNode extends AddressNode implements Simplifiable, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(AMD64AddressNode.class); @@ -64,6 +70,28 @@ public class AMD64AddressNode extends AddressNode implements LIRLowerable { this.scale = Scale.Times1; } + public void canonicalizeIndex(SimplifierTool tool) { + if (index instanceof AddNode) { + AddNode add = (AddNode) index; + ValueNode valX = add.getX(); + if (valX instanceof PhiNode) { + PhiNode phi = (PhiNode) valX; + if (phi.merge() instanceof LoopBeginNode) { + LoopBeginNode loopNode = (LoopBeginNode) phi.merge(); + if (!loopNode.isSimpleLoop()) { + ValueNode valY = add.getY(); + if (valY instanceof ConstantNode) { + int addBy = valY.asJavaConstant().asInt(); + displacement = displacement + scale.value * addBy; + replaceFirstInput(index, phi); + tool.addToWorkList(index); + } + } + } + } + } + } + @Override public void generate(NodeLIRBuilderTool gen) { LIRGeneratorTool tool = gen.getLIRGeneratorTool(); @@ -73,7 +101,9 @@ public class AMD64AddressNode extends AddressNode implements LIRLowerable { AllocatableValue baseReference = LIRKind.derivedBaseFromValue(baseValue); AllocatableValue indexReference; - if (scale.equals(Scale.Times1)) { + if (index == null) { + indexReference = null; + } else if (scale.equals(Scale.Times1)) { indexReference = LIRKind.derivedBaseFromValue(indexValue); } else { if (LIRKind.isValue(indexValue)) { @@ -87,6 +117,7 @@ public class AMD64AddressNode extends AddressNode implements LIRLowerable { gen.setResult(this, new AMD64AddressValue(kind, baseValue, indexValue, scale, displacement)); } + @Override public ValueNode getBase() { return base; } @@ -99,6 +130,7 @@ public class AMD64AddressNode extends AddressNode implements LIRLowerable { this.base = base; } + @Override public ValueNode getIndex() { return index; } @@ -126,4 +158,14 @@ public class AMD64AddressNode extends AddressNode implements LIRLowerable { public void setDisplacement(int displacement) { this.displacement = displacement; } + + @Override + public long getMaxConstantDisplacement() { + return displacement; + } + + @Override + public void simplify(SimplifierTool tool) { + canonicalizeIndex(tool); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java index 4eba24888a6..0971cf54b71 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java @@ -74,7 +74,7 @@ import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntr import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.EXP; import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp.BinaryIntrinsicOpcode.POW; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp; @@ -1234,7 +1234,7 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen return; } else if (c instanceof VMConstant) { VMConstant vc = (VMConstant) c; - if (size == DWORD && !GeneratePIC.getValue()) { + if (size == DWORD && !GeneratePIC.getValue(getOptions())) { getLIRGen().append(new AMD64BinaryConsumer.VMConstOp(CMP.getMIOpcode(DWORD, false), left, vc)); } else { getLIRGen().append(new AMD64BinaryConsumer.DataOp(CMP.getRMOpcode(size), size, left, vc)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java index f9d2f5c8e62..e207f830464 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java @@ -23,6 +23,7 @@ package org.graalvm.compiler.core.amd64; +import static jdk.vm.ci.code.ValueUtil.isAllocatableValue; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.CMP; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PD; @@ -31,10 +32,10 @@ import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.lir.LIRValueUtil.asConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant; +import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; -import static jdk.vm.ci.code.ValueUtil.isAllocatableValue; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; @@ -72,6 +73,7 @@ import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp; import org.graalvm.compiler.lir.amd64.AMD64Move.MembarOp; import org.graalvm.compiler.lir.amd64.AMD64Move.StackLeaOp; import org.graalvm.compiler.lir.amd64.AMD64PauseOp; +import org.graalvm.compiler.lir.amd64.AMD64StringIndexOfOp; import org.graalvm.compiler.lir.amd64.AMD64ZapRegistersOp; import org.graalvm.compiler.lir.amd64.AMD64ZapStackOp; import org.graalvm.compiler.lir.gen.LIRGenerationResult; @@ -112,10 +114,8 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { protected static final boolean canStoreConstant(JavaConstant c) { // there is no immediate move of 64-bit constants on Intel switch (c.getJavaKind()) { - case Long: { - long l = c.asLong(); - return (int) l == l; - } + case Long: + return NumUtil.isInt(c.asLong()); case Double: return false; case Object: @@ -183,7 +183,7 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { } @Override - public Variable emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + public Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { ValueKind kind = newValue.getValueKind(); assert kind.equals(expectedValue.getValueKind()); AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind(); @@ -199,6 +199,33 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { return result; } + @Override + public Value emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue) { + ValueKind kind = newValue.getValueKind(); + assert kind.equals(expectedValue.getValueKind()); + AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind(); + + AMD64AddressValue addressValue = asAddressValue(address); + RegisterValue raxRes = AMD64.rax.asValue(kind); + emitMove(raxRes, expectedValue); + append(new CompareAndSwapOp(memKind, raxRes, addressValue, raxRes, asAllocatable(newValue))); + Variable result = newVariable(kind); + emitMove(result, raxRes); + return result; + } + + public void emitCompareAndSwapBranch(ValueKind kind, AMD64AddressValue address, Value expectedValue, Value newValue, Condition condition, LabelRef trueLabel, LabelRef falseLabel, + double trueLabelProbability) { + assert kind.equals(expectedValue.getValueKind()); + assert kind.equals(newValue.getValueKind()); + assert condition == Condition.EQ || condition == Condition.NE; + AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind(); + RegisterValue raxValue = AMD64.rax.asValue(kind); + emitMove(raxValue, expectedValue); + append(new CompareAndSwapOp(memKind, raxValue, address, raxValue, asAllocatable(newValue))); + append(new BranchOp(condition, trueLabel, falseLabel, trueLabelProbability)); + } + @Override public Value emitAtomicReadAndAdd(Value address, Value delta) { ValueKind kind = delta.getValueKind(); @@ -329,7 +356,7 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { throw GraalError.shouldNotReachHere("unexpected kind: " + cmpKind); } - if (isJavaConstant(a)) { + if (isConstantValue(a)) { return emitCompareMemoryConOp(size, asConstantValue(a), b, state); } else { return emitCompareRegMemoryOp(size, asAllocatable(a), b, state); @@ -399,7 +426,7 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { @Override protected void emitForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { long maxOffset = linkage.getMaxCallTargetOffset(); - if (maxOffset != (int) maxOffset && !GeneratePIC.getValue()) { + if (maxOffset != (int) maxOffset && !GeneratePIC.getValue(getResult().getLIR().getOptions())) { append(new AMD64Call.DirectFarForeignCallOp(linkage, result, arguments, temps, info)); } else { append(new AMD64Call.DirectNearForeignCallOp(linkage, result, arguments, temps, info)); @@ -420,6 +447,24 @@ public abstract class AMD64LIRGenerator extends LIRGenerator { return result; } + /** + * Return a conservative estimate of the page size for use by the String.indexOf intrinsic. + */ + protected int getVMPageSize() { + return 4096; + } + + @Override + public Variable emitStringIndexOf(Value source, Value sourceCount, Value target, Value targetCount, int constantTargetCount) { + Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD)); + RegisterValue cnt1 = AMD64.rdx.asValue(sourceCount.getValueKind()); + emitMove(cnt1, sourceCount); + RegisterValue cnt2 = AMD64.rax.asValue(targetCount.getValueKind()); + emitMove(cnt2, targetCount); + append(new AMD64StringIndexOfOp(this, result, source, target, cnt1, cnt2, AMD64.rcx.asValue(), AMD64.xmm0.asValue(), constantTargetCount, getVMPageSize())); + return result; + } + @Override public void emitReturn(JavaKind kind, Value input) { AllocatableValue operand = Value.ILLEGAL; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRKindTool.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRKindTool.java index 7a0ad5bfc24..a2ff74c5f66 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRKindTool.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRKindTool.java @@ -66,4 +66,13 @@ public class AMD64LIRKindTool implements LIRKindTool { return LIRKind.value(AMD64Kind.QWORD); } + @Override + public LIRKind getNarrowOopKind() { + return LIRKind.reference(AMD64Kind.DWORD); + } + + @Override + public LIRKind getNarrowPointerKind() { + return LIRKind.value(AMD64Kind.DWORD); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java index fb767ee07fe..2e07cd3a23c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java @@ -23,16 +23,18 @@ package org.graalvm.compiler.core.amd64; +import static jdk.vm.ci.code.ValueUtil.isRegister; import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue; -import static jdk.vm.ci.code.ValueUtil.isRegister; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.type.DataPointerConstant; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.amd64.AMD64AddressValue; import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; +import org.graalvm.compiler.lir.amd64.AMD64Move; import org.graalvm.compiler.lir.amd64.AMD64Move.AMD64StackMove; import org.graalvm.compiler.lir.amd64.AMD64Move.LeaDataOp; import org.graalvm.compiler.lir.amd64.AMD64Move.LeaOp; @@ -54,15 +56,30 @@ public abstract class AMD64MoveFactory extends AMD64MoveFactoryBase { } @Override - public boolean canInlineConstant(JavaConstant c) { - switch (c.getJavaKind()) { - case Long: - return NumUtil.isInt(c.asLong()); - case Object: - return c.isNull(); - default: - return true; + public boolean canInlineConstant(Constant con) { + if (con instanceof JavaConstant) { + JavaConstant c = (JavaConstant) con; + switch (c.getJavaKind()) { + case Long: + return NumUtil.isInt(c.asLong()); + case Object: + return c.isNull(); + default: + return true; + } } + return false; + } + + @Override + public boolean allowConstantToStackMove(Constant constant) { + if (constant instanceof DataPointerConstant) { + return false; + } + if (constant instanceof JavaConstant && !AMD64Move.canMoveConst2Stack(((JavaConstant) constant))) { + return false; + } + return true; } @Override @@ -93,4 +110,13 @@ public abstract class AMD64MoveFactory extends AMD64MoveFactoryBase { throw GraalError.shouldNotReachHere(String.format("unsupported constant: %s", src)); } } + + @Override + public LIRInstruction createStackLoad(AllocatableValue result, Constant input) { + if (input instanceof JavaConstant) { + return new MoveFromConstOp(result, (JavaConstant) input); + } else { + throw GraalError.shouldNotReachHere(String.format("unsupported constant for stack load: %s", input)); + } + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java index 2ff74388f70..198998ae652 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java @@ -26,15 +26,14 @@ package org.graalvm.compiler.core.amd64; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.WORD; -import java.util.HashMap; -import java.util.Map; - import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; import org.graalvm.compiler.lir.amd64.AMD64Move.AMD64PushPopStackMove; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Architecture; @@ -61,7 +60,7 @@ public abstract class AMD64MoveFactoryBase implements MoveFactory { public static final class BackupSlotProvider { private final FrameMapBuilder frameMapBuilder; - private Map categorized; + private EconomicMap categorized; public BackupSlotProvider(FrameMapBuilder frameMapBuilder) { this.frameMapBuilder = frameMapBuilder; @@ -70,7 +69,7 @@ public abstract class AMD64MoveFactoryBase implements MoveFactory { protected RegisterBackupPair getScratchRegister(PlatformKind kind) { PlatformKind.Key key = kind.getKey(); if (categorized == null) { - categorized = new HashMap<>(); + categorized = EconomicMap.create(Equivalence.DEFAULT); } else if (categorized.containsKey(key)) { return categorized.get(key); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java index 7787dd0e565..760f599d08c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java @@ -36,22 +36,22 @@ import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SD; import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SS; -import org.graalvm.compiler.asm.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RRMOp; +import org.graalvm.compiler.asm.amd64.AMD64Assembler.AVXOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize; import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp; -import org.graalvm.compiler.asm.amd64.AMD64Assembler.AVXOp; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.core.gen.NodeMatchRules; import org.graalvm.compiler.core.match.ComplexMatchResult; import org.graalvm.compiler.core.match.MatchRule; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LIRValueUtil; import org.graalvm.compiler.lir.LabelRef; import org.graalvm.compiler.lir.amd64.AMD64AddressValue; import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer; @@ -69,18 +69,22 @@ import org.graalvm.compiler.nodes.calc.ReinterpretNode; import org.graalvm.compiler.nodes.calc.SignExtendNode; import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode; import org.graalvm.compiler.nodes.calc.ZeroExtendNode; +import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; +import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.Access; +import org.graalvm.compiler.nodes.memory.LIRLowerableAccess; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.util.GraphUtil; import jdk.vm.ci.amd64.AMD64; -import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.amd64.AMD64.CPUFeature; +import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.PlatformKind; import jdk.vm.ci.meta.Value; +import jdk.vm.ci.meta.ValueKind; public class AMD64NodeMatchRules extends NodeMatchRules { @@ -95,11 +99,15 @@ public class AMD64NodeMatchRules extends NodeMatchRules { return null; } - protected AMD64Kind getMemoryKind(Access access) { - return (AMD64Kind) gen.getLIRKind(access.asNode().stamp()).getPlatformKind(); + protected AMD64Kind getMemoryKind(LIRLowerableAccess access) { + return (AMD64Kind) getLirKind(access).getPlatformKind(); } - protected OperandSize getMemorySize(Access access) { + protected LIRKind getLirKind(LIRLowerableAccess access) { + return gen.getLIRKind(access.getAccessStamp()); + } + + protected OperandSize getMemorySize(LIRLowerableAccess access) { switch (getMemoryKind(access)) { case BYTE: return OperandSize.BYTE; @@ -118,25 +126,36 @@ public class AMD64NodeMatchRules extends NodeMatchRules { } } - protected ComplexMatchResult emitCompareBranchMemory(IfNode ifNode, CompareNode compare, ValueNode value, Access access) { + protected ComplexMatchResult emitCompareBranchMemory(IfNode ifNode, CompareNode compare, ValueNode value, LIRLowerableAccess access) { Condition cond = compare.condition(); AMD64Kind kind = getMemoryKind(access); + boolean matchedAsConstant = false; // For assertion checking if (value.isConstant()) { JavaConstant constant = value.asJavaConstant(); - if (constant != null && kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && !NumUtil.isInt(constant.asLong())) { - // Only imm32 as long - return null; + if (constant != null) { + if (kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && !NumUtil.isInt(constant.asLong())) { + // Only imm32 as long + return null; + } + // A QWORD that can be encoded as int can be embedded as a constant + matchedAsConstant = kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && NumUtil.isInt(constant.asLong()); + } + if (kind == AMD64Kind.DWORD) { + // Any DWORD value should be embeddable as a constant + matchedAsConstant = true; } if (kind.isXMM()) { - Debug.log("Skipping constant compares for float kinds"); + ifNode.getDebug().log("Skipping constant compares for float kinds"); return null; } } + boolean matchedAsConstantFinal = matchedAsConstant; - // emitCompareBranchMemory expects the memory on the right, so mirror the condition if - // that's not true. It might be mirrored again the actual compare is emitted but that's - // ok. + /* + * emitCompareBranchMemory expects the memory on the right, so mirror the condition if + * that's not true. It might be mirrored again the actual compare is emitted but that's ok. + */ Condition finalCondition = GraphUtil.unproxify(compare.getX()) == access ? cond.mirror() : cond; return new ComplexMatchResult() { @Override @@ -146,6 +165,11 @@ public class AMD64NodeMatchRules extends NodeMatchRules { boolean unorderedIsTrue = compare.unorderedIsTrue(); double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor()); Value other = operand(value); + /* + * Check that patterns which were matched as a constant actually end up seeing a + * constant in the LIR. + */ + assert !matchedAsConstantFinal || !LIRValueUtil.isVariable(other) : "expected constant value " + value; AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); getLIRGeneratorTool().emitCompareBranchMemory(kind, other, address, getState(access), finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability); return null; @@ -153,7 +177,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { }; } - private ComplexMatchResult emitIntegerTestBranchMemory(IfNode x, ValueNode value, Access access) { + private ComplexMatchResult emitIntegerTestBranchMemory(IfNode x, ValueNode value, LIRLowerableAccess access) { LabelRef trueLabel = getLIRBlock(x.trueSuccessor()); LabelRef falseLabel = getLIRBlock(x.falseSuccessor()); double trueLabelProbability = x.probability(x.trueSuccessor()); @@ -181,15 +205,22 @@ public class AMD64NodeMatchRules extends NodeMatchRules { } } - protected ComplexMatchResult emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, Access access) { + protected ComplexMatchResult emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, Access access, ValueKind addressKind) { return builder -> { AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); LIRFrameState state = getState(access); + if (addressKind != null) { + address = address.withKind(addressKind); + } return getArithmeticLIRGenerator().emitConvertMemoryOp(kind, op, size, address, state); }; } - private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits) { + protected ComplexMatchResult emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, Access access) { + return emitConvertMemoryOp(kind, op, size, access, null); + } + + private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits, ValueKind addressKind) { assert fromBits <= toBits && toBits <= 64; AMD64Kind kind = null; AMD64RMOp op; @@ -231,7 +262,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { } } if (kind != null && op != null) { - return emitConvertMemoryOp(kind, op, size, access); + return emitConvertMemoryOp(kind, op, size, access, addressKind); } return null; } @@ -244,7 +275,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(If (IntegerTest Read=access value))") @MatchRule("(If (IntegerTest FloatingRead=access value))") - public ComplexMatchResult integerTestBranchMemory(IfNode root, Access access, ValueNode value) { + public ComplexMatchResult integerTestBranchMemory(IfNode root, LIRLowerableAccess access, ValueNode value) { return emitIntegerTestBranchMemory(root, value, access); } @@ -262,7 +293,67 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(If (PointerEquals=compare value FloatingRead=access))") @MatchRule("(If (ObjectEquals=compare value Read=access))") @MatchRule("(If (ObjectEquals=compare value FloatingRead=access))") - public ComplexMatchResult ifCompareMemory(IfNode root, CompareNode compare, ValueNode value, Access access) { + public ComplexMatchResult ifCompareMemory(IfNode root, CompareNode compare, ValueNode value, LIRLowerableAccess access) { + return emitCompareBranchMemory(root, compare, value, access); + } + + @MatchRule("(If (ObjectEquals=compare value ValueCompareAndSwap=cas))") + @MatchRule("(If (PointerEquals=compare value ValueCompareAndSwap=cas))") + @MatchRule("(If (FloatEquals=compare value ValueCompareAndSwap=cas))") + @MatchRule("(If (IntegerEquals=compare value ValueCompareAndSwap=cas))") + public ComplexMatchResult ifCompareValueCas(IfNode root, CompareNode compare, ValueNode value, ValueCompareAndSwapNode cas) { + assert compare.condition() == Condition.EQ; + if (value == cas.getExpectedValue() && cas.usages().count() == 1) { + return builder -> { + LIRKind kind = getLirKind(cas); + LabelRef trueLabel = getLIRBlock(root.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(root.falseSuccessor()); + double trueLabelProbability = root.probability(root.trueSuccessor()); + Value expectedValue = operand(cas.getExpectedValue()); + Value newValue = operand(cas.getNewValue()); + AMD64AddressValue address = (AMD64AddressValue) operand(cas.getAddress()); + getLIRGeneratorTool().emitCompareAndSwapBranch(kind, address, expectedValue, newValue, Condition.EQ, trueLabel, falseLabel, trueLabelProbability); + return null; + }; + } + return null; + } + + @MatchRule("(If (ObjectEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (PointerEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (FloatEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (IntegerEquals=compare value LogicCompareAndSwap=cas))") + public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) { + JavaConstant constant = value.asJavaConstant(); + assert compare.condition() == Condition.EQ; + if (constant != null && cas.usages().count() == 1) { + long constantValue = constant.asLong(); + boolean successIsTrue; + if (constantValue == 0) { + successIsTrue = false; + } else if (constantValue == 1) { + successIsTrue = true; + } else { + return null; + } + return builder -> { + LIRKind kind = getLirKind(cas); + LabelRef trueLabel = getLIRBlock(root.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(root.falseSuccessor()); + double trueLabelProbability = root.probability(root.trueSuccessor()); + Value expectedValue = operand(cas.getExpectedValue()); + Value newValue = operand(cas.getNewValue()); + AMD64AddressValue address = (AMD64AddressValue) operand(cas.getAddress()); + Condition condition = successIsTrue ? Condition.EQ : Condition.NE; + getLIRGeneratorTool().emitCompareAndSwapBranch(kind, address, expectedValue, newValue, condition, trueLabel, falseLabel, trueLabelProbability); + return null; + }; + } + return null; + } + + @MatchRule("(If (ObjectEquals=compare value FloatingRead=access))") + public ComplexMatchResult ifLogicCas(IfNode root, CompareNode compare, ValueNode value, LIRLowerableAccess access) { return emitCompareBranchMemory(root, compare, value, access); } @@ -290,19 +381,19 @@ public class AMD64NodeMatchRules extends NodeMatchRules { return null; } - private ComplexMatchResult binaryRead(AMD64RMOp op, OperandSize size, ValueNode value, Access access) { + private ComplexMatchResult binaryRead(AMD64RMOp op, OperandSize size, ValueNode value, LIRLowerableAccess access) { return builder -> getArithmeticLIRGenerator().emitBinaryMemory(op, size, getLIRGeneratorTool().asAllocatable(operand(value)), (AMD64AddressValue) operand(access.getAddress()), getState(access)); } - private ComplexMatchResult binaryRead(AMD64RRMOp op, OperandSize size, ValueNode value, Access access) { + private ComplexMatchResult binaryRead(AMD64RRMOp op, OperandSize size, ValueNode value, LIRLowerableAccess access) { return builder -> getArithmeticLIRGenerator().emitBinaryMemory(op, size, getLIRGeneratorTool().asAllocatable(operand(value)), (AMD64AddressValue) operand(access.getAddress()), getState(access)); } @MatchRule("(Add value Read=access)") @MatchRule("(Add value FloatingRead=access)") - public ComplexMatchResult addMemory(ValueNode value, Access access) { + public ComplexMatchResult addMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { TargetDescription target = getLIRGeneratorTool().target(); @@ -319,7 +410,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Sub value Read=access)") @MatchRule("(Sub value FloatingRead=access)") - public ComplexMatchResult subMemory(ValueNode value, Access access) { + public ComplexMatchResult subMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { TargetDescription target = getLIRGeneratorTool().target(); @@ -336,7 +427,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Mul value Read=access)") @MatchRule("(Mul value FloatingRead=access)") - public ComplexMatchResult mulMemory(ValueNode value, Access access) { + public ComplexMatchResult mulMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { TargetDescription target = getLIRGeneratorTool().target(); @@ -353,7 +444,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(And value Read=access)") @MatchRule("(And value FloatingRead=access)") - public ComplexMatchResult andMemory(ValueNode value, Access access) { + public ComplexMatchResult andMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { return null; @@ -364,7 +455,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Or value Read=access)") @MatchRule("(Or value FloatingRead=access)") - public ComplexMatchResult orMemory(ValueNode value, Access access) { + public ComplexMatchResult orMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { return null; @@ -375,7 +466,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Xor value Read=access)") @MatchRule("(Xor value FloatingRead=access)") - public ComplexMatchResult xorMemory(ValueNode value, Access access) { + public ComplexMatchResult xorMemory(ValueNode value, LIRLowerableAccess access) { OperandSize size = getMemorySize(access); if (size.isXmmType()) { return null; @@ -395,20 +486,44 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(SignExtend Read=access)") @MatchRule("(SignExtend FloatingRead=access)") - public ComplexMatchResult signExtend(SignExtendNode root, Access access) { - return emitSignExtendMemory(access, root.getInputBits(), root.getResultBits()); + public ComplexMatchResult signExtend(SignExtendNode root, LIRLowerableAccess access) { + return emitSignExtendMemory(access, root.getInputBits(), root.getResultBits(), null); } @MatchRule("(ZeroExtend Read=access)") @MatchRule("(ZeroExtend FloatingRead=access)") - public ComplexMatchResult zeroExtend(ZeroExtendNode root, Access access) { + public ComplexMatchResult zeroExtend(ZeroExtendNode root, LIRLowerableAccess access) { AMD64Kind memoryKind = getMemoryKind(access); return builder -> getArithmeticLIRGenerator().emitZeroExtendMemory(memoryKind, root.getResultBits(), (AMD64AddressValue) operand(access.getAddress()), getState(access)); } + @MatchRule("(Narrow Read=access)") + @MatchRule("(Narrow FloatingRead=access)") + public ComplexMatchResult narrowRead(NarrowNode root, LIRLowerableAccess access) { + return new ComplexMatchResult() { + @Override + public Value evaluate(NodeLIRBuilder builder) { + AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress()); + LIRKind addressKind = LIRKind.combineDerived(getLIRGeneratorTool().getLIRKind(root.asNode().stamp()), + address.getBase(), address.getIndex()); + AMD64AddressValue newAddress = address.withKind(addressKind); + LIRKind readKind = getLIRGeneratorTool().getLIRKind(root.stamp()); + return getArithmeticLIRGenerator().emitZeroExtendMemory((AMD64Kind) readKind.getPlatformKind(), + root.getResultBits(), newAddress, getState(access)); + } + }; + } + + @MatchRule("(SignExtend (Narrow=narrow Read=access))") + @MatchRule("(SignExtend (Narrow=narrow FloatingRead=access))") + public ComplexMatchResult signExtendNarrowRead(SignExtendNode root, NarrowNode narrow, LIRLowerableAccess access) { + LIRKind kind = getLIRGeneratorTool().getLIRKind(narrow.stamp()); + return emitSignExtendMemory(access, narrow.getResultBits(), root.getResultBits(), kind); + } + @MatchRule("(FloatConvert Read=access)") @MatchRule("(FloatConvert FloatingRead=access)") - public ComplexMatchResult floatConvert(FloatConvertNode root, Access access) { + public ComplexMatchResult floatConvert(FloatConvertNode root, LIRLowerableAccess access) { switch (root.getFloatConvert()) { case D2F: return emitConvertMemoryOp(AMD64Kind.SINGLE, SSEOp.CVTSD2SS, SD, access); @@ -437,7 +552,7 @@ public class AMD64NodeMatchRules extends NodeMatchRules { @MatchRule("(Reinterpret Read=access)") @MatchRule("(Reinterpret FloatingRead=access)") - public ComplexMatchResult reinterpret(ReinterpretNode root, Access access) { + public ComplexMatchResult reinterpret(ReinterpretNode root, LIRLowerableAccess access) { return builder -> { LIRKind kind = getLIRGeneratorTool().getLIRKind(root.stamp()); return emitReinterpretMemory(kind, access); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesCreator.java similarity index 80% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesProvider.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesCreator.java index 99ecbb711c9..e8c9936dcbd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesCreator.java @@ -22,22 +22,23 @@ */ package org.graalvm.compiler.core.amd64; -import org.graalvm.compiler.java.DefaultSuitesProvider; +import org.graalvm.compiler.java.DefaultSuitesCreator; import org.graalvm.compiler.lir.amd64.phases.StackMoveOptimizationPhase; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; -public class AMD64SuitesProvider extends DefaultSuitesProvider { +public class AMD64SuitesCreator extends DefaultSuitesCreator { - public AMD64SuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) { + public AMD64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) { super(compilerConfiguration, plugins); } @Override - public LIRSuites createLIRSuites() { - LIRSuites lirSuites = super.createLIRSuites(); - if (StackMoveOptimizationPhase.Options.LIROptStackMoveOptimizer.getValue()) { + public LIRSuites createLIRSuites(OptionValues options) { + LIRSuites lirSuites = super.createLIRSuites(options); + if (StackMoveOptimizationPhase.Options.LIROptStackMoveOptimizer.getValue(options)) { /* Note: this phase must be inserted after RedundantMoveElimination */ lirSuites.getPostAllocationOptimizationStage().appendPhase(new StackMoveOptimizationPhase()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/InstrumentationInliningCallback.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CancellationBailoutException.java similarity index 63% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/InstrumentationInliningCallback.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CancellationBailoutException.java index 8964954d5b9..0711203bb47 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/InstrumentationInliningCallback.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CancellationBailoutException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -20,17 +20,22 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.nodes.debug.instrumentation; +package org.graalvm.compiler.core.common; /** - * Nodes implementing {@code InstrumentationInliningCallback} will be notify of the - * preInlineInstrumentation event and the postInlineInstrumentation event upon inlining - * instrumentation. + * A {@linkplain RetryableBailoutException} that will be thrown if an on-going compilation in the + * compiler was cancelled. */ -public interface InstrumentationInliningCallback { +public final class CancellationBailoutException extends RetryableBailoutException { - void preInlineInstrumentation(InstrumentationNode instrumentation); + private static final long serialVersionUID = 6551793589275293360L; - void postInlineInstrumentation(InstrumentationNode instrumentation); + public CancellationBailoutException() { + super("Compilation cancelled."); + } + + public static void cancelCompilation() { + throw new CancellationBailoutException(); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CollectionsFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CollectionsFactory.java deleted file mode 100644 index 072372e5c7c..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CollectionsFactory.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.common; - -import static org.graalvm.compiler.core.common.CollectionsFactory.Mode.STANDARD; - -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.IdentityHashMap; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -/** - * Factory for creating collection objects used during compilation. - */ -public class CollectionsFactory { - - private static final ThreadLocal tl = new ThreadLocal<>(); - - public static class ModeScope implements AutoCloseable { - private final Mode previousMode; - - public ModeScope(Mode previousMode) { - this.previousMode = previousMode; - } - - @Override - public void close() { - tl.set(previousMode); - } - } - - /** - * Constants denoting what type of collections are {@link CollectionsFactory#getMode() - * currently} returned by the factory. - */ - public enum Mode { - /** - * Denotes standard collections such as {@link HashSet} and {@link HashMap}. - */ - STANDARD, - - /** - * Denotes collections that have a deterministic iteration order over their keys/entries. - */ - DETERMINISTIC_ITERATION_ORDER; - } - - /** - * Gets the current mode determining the type of collection objects created by this factory. - */ - public static Mode getMode() { - Mode mode = tl.get(); - return mode == null ? Mode.STANDARD : mode; - } - - /** - * Updates the mode for the current thread. - * - * @return an object which when {@linkplain ModeScope#close() closed} will revert the mode of - * the current thread to the state before calling this method - */ - public static ModeScope changeMode(Mode mode) { - Mode previousMode = tl.get(); - tl.set(mode); - return new ModeScope(previousMode); - } - - public static HashMap newMap() { - return getMode() == STANDARD ? new HashMap<>() : new LinkedHashMap<>(); - } - - public static HashMap newMap(Map m) { - return getMode() == STANDARD ? new HashMap<>(m) : new LinkedHashMap<>(m); - } - - public static HashMap newMap(int initialCapacity) { - return getMode() == STANDARD ? new HashMap<>(initialCapacity) : new LinkedHashMap<>(initialCapacity); - } - - public static Map newIdentityMap() { - return getMode() == STANDARD ? new IdentityHashMap<>() : new LinkedIdentityHashMap<>(); - } - - public static Map newIdentityMap(int expectedMaxSize) { - return getMode() == STANDARD ? new IdentityHashMap<>(expectedMaxSize) : new LinkedIdentityHashMap<>(); - } - - public static Map newIdentityMap(Map m) { - return getMode() == STANDARD ? new IdentityHashMap<>(m) : new LinkedIdentityHashMap<>(m); - } - - /** - * Creates a set. If the current thread is {@linkplain CollectionsFactory#getMode() using} - * {@link Mode#DETERMINISTIC_ITERATION_ORDER} collections, the returned set will have an - * iteration order determined by the order in which elements are inserted in the set. - */ - public static Set newSet() { - return CollectionsFactory.getMode() == Mode.STANDARD ? new HashSet<>() : new LinkedHashSet<>(); - } - - /** - * @see #newSet() - */ - public static Set newSet(Collection c) { - return CollectionsFactory.getMode() == Mode.STANDARD ? new HashSet<>(c) : new LinkedHashSet<>(c); - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompressEncoding.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CompressEncoding.java similarity index 75% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompressEncoding.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CompressEncoding.java index 9a0a8d22215..4eac53452cb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompressEncoding.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CompressEncoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -20,20 +20,18 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.hotspot; +package org.graalvm.compiler.core.common; /** * A compact representation of the different encoding strategies for Objects and metadata. */ -public class CompressEncoding { - public final long base; - public final int shift; - public final int alignment; +public final class CompressEncoding { + private final long base; + private final int shift; - CompressEncoding(long base, int shift, int alignment) { + public CompressEncoding(long base, int shift) { this.base = base; this.shift = shift; - this.alignment = alignment; } public int compress(long ptr) { @@ -44,6 +42,22 @@ public class CompressEncoding { } } + public boolean hasBase() { + return base != 0; + } + + public boolean hasShift() { + return shift != 0; + } + + public long getBase() { + return base; + } + + public int getShift() { + return shift; + } + public long uncompress(int ptr) { if (ptr == 0) { return 0L; @@ -54,14 +68,13 @@ public class CompressEncoding { @Override public String toString() { - return "base: " + base + " shift: " + shift + " alignment: " + alignment; + return "base: " + base + " shift: " + shift; } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + alignment; result = prime * result + (int) (base ^ (base >>> 32)); result = prime * result + shift; return result; @@ -71,7 +84,7 @@ public class CompressEncoding { public boolean equals(Object obj) { if (obj instanceof CompressEncoding) { CompressEncoding other = (CompressEncoding) obj; - return alignment == other.alignment && base == other.base && shift == other.shift; + return base == other.base && shift == other.shift; } else { return false; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java index 68d158db3b8..8bb79f7b485 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java @@ -23,9 +23,8 @@ package org.graalvm.compiler.core.common; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; /** * This class encapsulates options that control the behavior of the Graal compiler. @@ -34,250 +33,242 @@ import org.graalvm.compiler.options.StableOptionValue; public final class GraalOptions { @Option(help = "Use compiler intrinsifications.", type = OptionType.Debug) - public static final OptionValue Intrinsify = new OptionValue<>(true); + public static final OptionKey Intrinsify = new OptionKey<>(true); @Option(help = "Inline calls with monomorphic type profile.", type = OptionType.Expert) - public static final OptionValue InlineMonomorphicCalls = new OptionValue<>(true); + public static final OptionKey InlineMonomorphicCalls = new OptionKey<>(true); @Option(help = "Inline calls with polymorphic type profile.", type = OptionType.Expert) - public static final OptionValue InlinePolymorphicCalls = new OptionValue<>(true); + public static final OptionKey InlinePolymorphicCalls = new OptionKey<>(true); @Option(help = "Inline calls with megamorphic type profile (i.e., not all types could be recorded).", type = OptionType.Expert) - public static final OptionValue InlineMegamorphicCalls = new OptionValue<>(true); + public static final OptionKey InlineMegamorphicCalls = new OptionKey<>(true); @Option(help = "Maximum desired size of the compiler graph in nodes.", type = OptionType.User) - public static final OptionValue MaximumDesiredSize = new OptionValue<>(20000); + public static final OptionKey MaximumDesiredSize = new OptionKey<>(20000); @Option(help = "Minimum probability for methods to be inlined for megamorphic type profiles.", type = OptionType.Expert) - public static final OptionValue MegamorphicInliningMinMethodProbability = new OptionValue<>(0.33D); + public static final OptionKey MegamorphicInliningMinMethodProbability = new OptionKey<>(0.33D); @Option(help = "Maximum level of recursive inlining.", type = OptionType.Expert) - public static final OptionValue MaximumRecursiveInlining = new OptionValue<>(5); + public static final OptionKey MaximumRecursiveInlining = new OptionKey<>(5); @Option(help = "Graphs with less than this number of nodes are trivial and therefore always inlined.", type = OptionType.Expert) - public static final OptionValue TrivialInliningSize = new OptionValue<>(10); + public static final OptionKey TrivialInliningSize = new OptionKey<>(10); @Option(help = "Inlining is explored up to this number of nodes in the graph for each call site.", type = OptionType.Expert) - public static final OptionValue MaximumInliningSize = new OptionValue<>(300); + public static final OptionKey MaximumInliningSize = new OptionKey<>(300); @Option(help = "If the previous low-level graph size of the method exceeds the threshold, it is not inlined.", type = OptionType.Expert) - public static final OptionValue SmallCompiledLowLevelGraphSize = new OptionValue<>(300); + public static final OptionKey SmallCompiledLowLevelGraphSize = new OptionKey<>(300); @Option(help = "", type = OptionType.Expert) - public static final OptionValue LimitInlinedInvokes = new OptionValue<>(5.0); + public static final OptionKey LimitInlinedInvokes = new OptionKey<>(5.0); @Option(help = "", type = OptionType.Expert) - public static final OptionValue InlineEverything = new OptionValue<>(false); + public static final OptionKey InlineEverything = new OptionKey<>(false); // escape analysis settings @Option(help = "", type = OptionType.Debug) - public static final OptionValue PartialEscapeAnalysis = new OptionValue<>(true); + public static final OptionKey PartialEscapeAnalysis = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue EscapeAnalysisIterations = new OptionValue<>(2); + public static final OptionKey EscapeAnalysisIterations = new OptionKey<>(2); @Option(help = "", type = OptionType.Debug) - public static final OptionValue EscapeAnalysisLoopCutoff = new OptionValue<>(20); + public static final OptionKey EscapeAnalysisLoopCutoff = new OptionKey<>(20); @Option(help = "", type = OptionType.Debug) - public static final OptionValue EscapeAnalyzeOnly = new OptionValue<>(null); + public static final OptionKey EscapeAnalyzeOnly = new OptionKey<>(null); @Option(help = "", type = OptionType.Expert) - public static final OptionValue MaximumEscapeAnalysisArrayLength = new OptionValue<>(32); + public static final OptionKey MaximumEscapeAnalysisArrayLength = new OptionKey<>(32); @Option(help = "", type = OptionType.Debug) - public static final OptionValue PEAInliningHints = new OptionValue<>(false); + public static final OptionKey PEAInliningHints = new OptionKey<>(false); @Option(help = "", type = OptionType.Expert) - public static final OptionValue TailDuplicationProbability = new OptionValue<>(0.5); + public static final OptionKey TailDuplicationProbability = new OptionKey<>(0.5); @Option(help = "", type = OptionType.Expert) - public static final OptionValue TailDuplicationTrivialSize = new OptionValue<>(1); + public static final OptionKey TailDuplicationTrivialSize = new OptionKey<>(1); @Option(help = "", type = OptionType.Expert) - public static final OptionValue DeoptsToDisableOptimisticOptimization = new OptionValue<>(40); + public static final OptionKey DeoptsToDisableOptimisticOptimization = new OptionKey<>(40); @Option(help = "", type = OptionType.Debug) - public static final OptionValue LoopPeeling = new OptionValue<>(true); + public static final OptionKey LoopPeeling = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ReassociateInvariants = new OptionValue<>(true); + public static final OptionKey ReassociateInvariants = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue FullUnroll = new OptionValue<>(true); + public static final OptionKey FullUnroll = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue LoopUnswitch = new OptionValue<>(true); + public static final OptionKey LoopUnswitch = new OptionKey<>(true); + + @Option(help = "", type = OptionType.Debug) + public static final OptionKey PartialUnroll = new OptionKey<>(true); @Option(help = "", type = OptionType.Expert) - public static final OptionValue MinimumPeelProbability = new OptionValue<>(0.35f); + public static final OptionKey MinimumPeelProbability = new OptionKey<>(0.35f); @Option(help = "", type = OptionType.Expert) - public static final OptionValue LoopMaxUnswitch = new OptionValue<>(3); + public static final OptionKey LoopMaxUnswitch = new OptionKey<>(3); @Option(help = "", type = OptionType.Debug) - public static final OptionValue UseLoopLimitChecks = new OptionValue<>(true); + public static final OptionKey UseLoopLimitChecks = new OptionKey<>(true); // debugging settings @Option(help = "", type = OptionType.Debug) - public static final OptionValue ZapStackOnMethodEntry = new OptionValue<>(false); + public static final OptionKey ZapStackOnMethodEntry = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue DeoptALot = new OptionValue<>(false); + public static final OptionKey DeoptALot = new OptionKey<>(false); @Option(help = "Stress the code emitting explicit exception throwing code.", type = OptionType.Debug) - public static final OptionValue StressExplicitExceptionCode = new OptionValue<>(false); + public static final OptionKey StressExplicitExceptionCode = new OptionKey<>(false); @Option(help = "Stress the code emitting invokes with explicit exception edges.", type = OptionType.Debug) - public static final OptionValue StressInvokeWithExceptionNode = new OptionValue<>(false); + public static final OptionKey StressInvokeWithExceptionNode = new OptionKey<>(false); + + @Option(help = "Stress the code by emitting reads at earliest instead of latest point.", type = OptionType.Debug) + public static final OptionKey StressTestEarlyReads = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue VerifyPhases = new OptionValue<>(false); + public static final OptionKey VerifyPhases = new OptionKey<>(false); // Debug settings: @Option(help = "", type = OptionType.Debug) - public static final OptionValue GCDebugStartCycle = new OptionValue<>(-1); + public static final OptionKey GCDebugStartCycle = new OptionKey<>(-1); @Option(help = "Perform platform dependent validation of the Java heap at returns", type = OptionType.Debug) - public static final OptionValue VerifyHeapAtReturn = new OptionValue<>(false); + public static final OptionKey VerifyHeapAtReturn = new OptionKey<>(false); // Other printing settings @Option(help = "Print profiling information when parsing a method's bytecode", type = OptionType.Debug) - public static final OptionValue PrintProfilingInformation = new OptionValue<>(false); + public static final OptionKey PrintProfilingInformation = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final StableOptionValue TraceEscapeAnalysis = new StableOptionValue<>(false); + public static final OptionKey TraceEscapeAnalysis = new OptionKey<>(false); // HotSpot command line options @Option(help = "Print inlining optimizations", type = OptionType.Debug) - public static final OptionValue HotSpotPrintInlining = new OptionValue<>(false); + public static final OptionKey HotSpotPrintInlining = new OptionKey<>(false); // Register allocator debugging @Option(help = "Comma separated list of registers that register allocation is limited to.", type = OptionType.Debug) - public static final OptionValue RegisterPressure = new OptionValue<>(null); + public static final OptionKey RegisterPressure = new OptionKey<>(null); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ConditionalElimination = new OptionValue<>(true); + public static final OptionKey ConditionalElimination = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue RemoveNeverExecutedCode = new OptionValue<>(true); + public static final OptionKey RawConditionalElimination = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue UseExceptionProbability = new OptionValue<>(true); + public static final OptionKey ReplaceInputsWithConstantsBasedOnStamps = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue UseExceptionProbabilityForOperations = new OptionValue<>(true); + public static final OptionKey RemoveNeverExecutedCode = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OmitHotExceptionStacktrace = new OptionValue<>(false); + public static final OptionKey UseExceptionProbability = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue GenSafepoints = new OptionValue<>(true); + public static final OptionKey OmitHotExceptionStacktrace = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue GenLoopSafepoints = new OptionValue<>(true); + public static final OptionKey GenSafepoints = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue UseTypeCheckHints = new OptionValue<>(true); + public static final OptionKey GenLoopSafepoints = new OptionKey<>(true); + + @Option(help = "", type = OptionType.Debug) + public static final OptionKey UseTypeCheckHints = new OptionKey<>(true); @Option(help = "", type = OptionType.Expert) - public static final OptionValue InlineVTableStubs = new OptionValue<>(true); + public static final OptionKey InlineVTableStubs = new OptionKey<>(true); @Option(help = "", type = OptionType.Expert) - public static final OptionValue AlwaysInlineVTableStubs = new OptionValue<>(false); + public static final OptionKey AlwaysInlineVTableStubs = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ResolveClassBeforeStaticInvoke = new OptionValue<>(false); + public static final OptionKey ResolveClassBeforeStaticInvoke = new OptionKey<>(false); @Option(help = "", type = OptionType.Debug) - public static final OptionValue CanOmitFrame = new OptionValue<>(true); + public static final OptionKey CanOmitFrame = new OptionKey<>(true); // Ahead of time compilation @Option(help = "Try to avoid emitting code where patching is required", type = OptionType.Expert) - public static final OptionValue ImmutableCode = new OptionValue<>(false); + public static final OptionKey ImmutableCode = new OptionKey<>(false); @Option(help = "Generate position independent code", type = OptionType.Expert) - public static final OptionValue GeneratePIC = new OptionValue<>(false); + public static final OptionKey GeneratePIC = new OptionKey<>(false); @Option(help = "", type = OptionType.Expert) - public static final OptionValue CallArrayCopy = new OptionValue<>(true); + public static final OptionKey CallArrayCopy = new OptionKey<>(true); // Runtime settings @Option(help = "", type = OptionType.Expert) - public static final OptionValue SupportJsrBytecodes = new OptionValue<>(true); + public static final OptionKey SupportJsrBytecodes = new OptionKey<>(true); @Option(help = "", type = OptionType.Expert) - public static final OptionValue OptAssumptions = new OptionValue<>(true); + public static final OptionKey OptAssumptions = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptConvertDeoptsToGuards = new OptionValue<>(true); + public static final OptionKey OptConvertDeoptsToGuards = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptReadElimination = new OptionValue<>(true); + public static final OptionKey OptReadElimination = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue ReadEliminationMaxLoopVisits = new OptionValue<>(5); + public static final OptionKey ReadEliminationMaxLoopVisits = new OptionKey<>(5); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptDeoptimizationGrouping = new OptionValue<>(true); + public static final OptionKey OptDeoptimizationGrouping = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptScheduleOutOfLoops = new OptionValue<>(true); + public static final OptionKey OptScheduleOutOfLoops = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptEliminateGuards = new OptionValue<>(true); + public static final OptionKey OptEliminateGuards = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptImplicitNullChecks = new OptionValue<>(true); + public static final OptionKey OptImplicitNullChecks = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptClearNonLiveLocals = new OptionValue<>(true); + public static final OptionKey OptClearNonLiveLocals = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptLoopTransform = new OptionValue<>(true); + public static final OptionKey OptLoopTransform = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptFloatingReads = new OptionValue<>(true); + public static final OptionKey OptFloatingReads = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptEliminatePartiallyRedundantGuards = new OptionValue<>(true); + public static final OptionKey OptEliminatePartiallyRedundantGuards = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptFilterProfiledTypes = new OptionValue<>(true); + public static final OptionKey OptFilterProfiledTypes = new OptionKey<>(true); @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptDevirtualizeInvokesOptimistically = new OptionValue<>(true); - - @Option(help = "", type = OptionType.Debug) - public static final OptionValue OptPushThroughPi = new OptionValue<>(true); + public static final OptionKey OptDevirtualizeInvokesOptimistically = new OptionKey<>(true); @Option(help = "Allow backend to match complex expressions.", type = OptionType.Debug) - public static final OptionValue MatchExpressions = new OptionValue<>(true); + public static final OptionKey MatchExpressions = new OptionKey<>(true); @Option(help = "Enable counters for various paths in snippets.", type = OptionType.Debug) - public static final OptionValue SnippetCounters = new OptionValue<>(false); + public static final OptionKey SnippetCounters = new OptionKey<>(false); @Option(help = "Eagerly construct extra snippet info.", type = OptionType.Debug) - public static final OptionValue EagerSnippets = new OptionValue<>(false); + public static final OptionKey EagerSnippets = new OptionKey<>(false); @Option(help = "Use a cache for snippet graphs.", type = OptionType.Debug) - public static final OptionValue UseSnippetGraphCache = new OptionValue<>(true); - - @Option(help = "Enable expensive assertions", type = OptionType.Debug) - public static final OptionValue DetailedAsserts = new StableOptionValue() { - @Override - protected Boolean defaultValue() { - boolean enabled = false; - // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this) - assert (enabled = true) == true; - return enabled; - } - }; - - @Option(help = "Enable Graal instrumentation") - public static final OptionValue UseGraalInstrumentation = new OptionValue<>(false); + public static final OptionKey UseSnippetGraphCache = new OptionKey<>(true); @Option(help = "Enable experimental Trace Register Allocation.", type = OptionType.Debug) - public static final OptionValue TraceRA = new OptionValue<>(false); + public static final OptionKey TraceRA = new OptionKey<>(false); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LIRKind.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LIRKind.java index 2b26f8f2506..688a328a006 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LIRKind.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LIRKind.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.common; -import java.util.ArrayList; +import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.meta.AllocatableValue; @@ -169,23 +169,6 @@ public final class LIRKind extends ValueKind { return inputs[0].getValueKind(LIRKind.class); } - /** - * Merge the types of the inputs. The result will have the {@link PlatformKind} of one of the - * inputs. If all inputs are values (references), the result is a value (reference). Otherwise, - * the result is an unknown reference. - * - * This method should be used to construct the result {@link LIRKind} of merge operation that - * does not modify values (e.g. phis). - */ - public static LIRKind merge(Value... inputs) { - assert inputs.length > 0; - ArrayList kinds = new ArrayList<>(inputs.length); - for (int i = 0; i < inputs.length; i++) { - kinds.add(inputs[i].getValueKind(LIRKind.class)); - } - return merge(kinds); - } - /** * Helper method to construct derived reference kinds. Returns the base value of a reference or * derived reference. For values it returns {@code null}, and for unknown references it returns @@ -228,62 +211,62 @@ public final class LIRKind extends ValueKind { } /** - * @see #merge(Value...) + * Merges the reference information of the inputs. The result will have the {@link PlatformKind} + * of {@code mergeKind}. If all inputs are values (references), the result is a value + * (reference). Otherwise, the result is an unknown reference. + * + * The correctness of the {@link PlatformKind} is not verified. */ - public static LIRKind merge(Iterable kinds) { - LIRKind mergeKind = null; + public static LIRKind mergeReferenceInformation(LIRKind mergeKind, LIRKind inputKind) { + assert mergeKind != null; + assert inputKind != null; - for (LIRKind kind : kinds) { + if (mergeKind.isUnknownReference()) { + /** + * {@code mergeKind} is an unknown reference, therefore the result can only be also an + * unknown reference. + */ + return mergeKind; + } - if (kind.isUnknownReference()) { - /** - * Kind is an unknown reference, therefore the result can only be also an unknown - * reference. + if (mergeKind.isValue()) { + /* {@code mergeKind} is a value. */ + if (!inputKind.isValue()) { + /* + * Inputs consists of values and references. Make the result an unknown reference. */ - mergeKind = kind; - break; + return mergeKind.makeUnknownReference(); } - if (mergeKind == null) { - mergeKind = kind; - continue; - } - - if (kind.isValue()) { - /* Kind is a value. */ - if (mergeKind.referenceMask != 0) { - /* - * Inputs consists of values and references. Make the result an unknown - * reference. - */ - mergeKind = mergeKind.makeUnknownReference(); - break; - } - /* Check that other inputs are also values. */ - } else { - /* Kind is a reference. */ - if (mergeKind.referenceMask != kind.referenceMask) { - /* - * Reference maps do not match so the result can only be an unknown reference. - */ - mergeKind = mergeKind.makeUnknownReference(); - break; - } - } - + return mergeKind; + } + /* {@code mergeKind} is a reference. */ + if (mergeKind.referenceMask != inputKind.referenceMask) { + /* + * Reference masks do not match so the result can only be an unknown reference. + */ + return mergeKind.makeUnknownReference(); } - assert mergeKind != null && verifyMerge(mergeKind, kinds); - // all inputs are values or references, just return one of them + /* Both are references. */ + if (mergeKind.isDerivedReference()) { + if (inputKind.isDerivedReference() && mergeKind.getDerivedReferenceBase().equals(inputKind.getDerivedReferenceBase())) { + /* Same reference base so they must be equal. */ + return mergeKind; + } + /* Base pointers differ. Make the result an unknown reference. */ + return mergeKind.makeUnknownReference(); + } + if (inputKind.isDerivedReference()) { + /* + * {@code mergeKind} is not derived but {@code inputKind} is. Make the result an unknown + * reference. + */ + return mergeKind.makeUnknownReference(); + } + /* Both are not derived references so they must be equal. */ return mergeKind; } - private static boolean verifyMerge(LIRKind mergeKind, Iterable kinds) { - for (LIRKind kind : kinds) { - assert mergeKind == null || verifyMoveKinds(mergeKind, kind) : String.format("Input kinds do not match %s vs. %s", mergeKind, kind); - } - return true; - } - /** * Create a new {@link LIRKind} with the same reference information and a new * {@linkplain #getPlatformKind platform kind}. If the new kind is a longer vector than this, @@ -447,6 +430,7 @@ public final class LIRKind extends ValueKind { final int prime = 31; int result = 1; result = prime * result + ((getPlatformKind() == null) ? 0 : getPlatformKind().hashCode()); + result = prime * result + ((getDerivedReferenceBase() == null) ? 0 : getDerivedReferenceBase().hashCode()); result = prime * result + referenceMask; return result; } @@ -461,16 +445,37 @@ public final class LIRKind extends ValueKind { } LIRKind other = (LIRKind) obj; - return getPlatformKind() == other.getPlatformKind() && referenceMask == other.referenceMask; + if (getPlatformKind() != other.getPlatformKind() || referenceMask != other.referenceMask) { + return false; + } + if (isDerivedReference()) { + if (!other.isDerivedReference()) { + return false; + } + return getDerivedReferenceBase().equals(other.getDerivedReferenceBase()); + } + // `this` is not a derived reference + if (other.isDerivedReference()) { + return false; + } + return true; } - public static boolean verifyMoveKinds(ValueKind dst, ValueKind src) { + public static boolean verifyMoveKinds(ValueKind dst, ValueKind src, RegisterAllocationConfig config) { if (src.equals(dst)) { return true; } - if (src.getPlatformKind().equals(dst.getPlatformKind())) { - return !isUnknownReference(src) || isUnknownReference(dst); + if (isUnknownReference(dst) || isValue(dst) && isValue(src)) { + PlatformKind srcPlatformKind = src.getPlatformKind(); + PlatformKind dstPlatformKind = dst.getPlatformKind(); + if (srcPlatformKind.equals(dstPlatformKind)) { + return true; + } + // if the register category matches it should be fine, although the kind is different + return config.getRegisterCategory(srcPlatformKind).equals(config.getRegisterCategory(dstPlatformKind)); } + // reference information mismatch return false; } + } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LinkedIdentityHashMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LinkedIdentityHashMap.java deleted file mode 100644 index 7c1aca0bdc6..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LinkedIdentityHashMap.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.common; - -import java.util.AbstractSet; -import java.util.Collection; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Set; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.function.Consumer; - -/** - * A map that combines {@link IdentityHashMap} with {@link LinkedHashMap} for the purpose of - * ensuring a deterministic execution order during a capturing compilation. - */ -final class LinkedIdentityHashMap implements Map { - - private final LinkedHashMap, V> map; - - LinkedIdentityHashMap() { - map = new LinkedHashMap<>(); - } - - LinkedIdentityHashMap(Map m) { - map = new LinkedHashMap<>(m.size()); - putAll(m); - } - - LinkedIdentityHashMap(int expectedMaxSize) { - map = new LinkedHashMap<>(expectedMaxSize); - } - - /** - * Wrapper for an object that gives uses the object's identity for the purpose of equality - * comparisons and computing a hash code. - */ - static final class Id { - final T object; - - Id(T object) { - assert object != null; - this.object = object; - } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object obj) { - return obj instanceof Id && ((Id) obj).object == object; - } - - @Override - public int hashCode() { - return System.identityHashCode(object); - } - } - - @Override - public int size() { - return map.size(); - } - - @Override - public boolean isEmpty() { - return map.isEmpty(); - } - - @Override - public boolean containsKey(Object key) { - return map.containsKey(id(key)); - } - - @SuppressWarnings("unchecked") - private Id id(Object key) { - if (key == null) { - return null; - } - return new Id<>((K) key); - } - - @Override - public boolean containsValue(Object value) { - return map.containsValue(value); - } - - @Override - public V get(Object key) { - return map.get(id(key)); - } - - @Override - public V put(K key, V value) { - return map.put(id(key), value); - } - - @Override - public V remove(Object key) { - return map.remove(id(key)); - } - - @Override - @SuppressWarnings("unchecked") - public void putAll(Map m) { - if (m == null) { - throw new NullPointerException(); - } - if (m.getClass() == getClass()) { - LinkedIdentityHashMap that = (LinkedIdentityHashMap) m; - map.putAll(that.map); - - } else { - for (K key : m.keySet()) { - map.put(id(key), m.get(key)); - } - } - } - - @Override - public void clear() { - map.clear(); - } - - final class KeySet extends AbstractSet { - @Override - public int size() { - return map.size(); - } - - @Override - public void clear() { - map.clear(); - } - - @Override - public Iterator iterator() { - return new Iterator() { - final Iterator> i = map.keySet().iterator(); - - @Override - public boolean hasNext() { - return i.hasNext(); - } - - @Override - public K next() { - return i.next().object; - } - - @Override - public void remove() { - i.remove(); - } - }; - } - - @Override - public boolean contains(Object o) { - return containsKey(o); - } - - @Override - public boolean remove(Object o) { - return LinkedIdentityHashMap.this.remove(o) != null; - } - - @Override - public Spliterator spliterator() { - return Spliterators.spliterator(this, Spliterator.SIZED | Spliterator.ORDERED | Spliterator.DISTINCT); - } - - @Override - public void forEach(Consumer action) { - throw new UnsupportedOperationException(); - } - } - - @Override - public Set keySet() { - return new KeySet(); - } - - @Override - public Collection values() { - return map.values(); - } - - final class EntrySet extends AbstractSet> { - @Override - public int size() { - return map.size(); - } - - @Override - public void clear() { - map.clear(); - } - - @Override - public Iterator> iterator() { - return new Iterator>() { - final Iterator, V>> i = map.entrySet().iterator(); - - @Override - public boolean hasNext() { - return i.hasNext(); - } - - @Override - public Map.Entry next() { - Map.Entry, V> e = i.next(); - return new Map.Entry() { - - @Override - public K getKey() { - return e.getKey().object; - } - - @Override - public V getValue() { - return e.getValue(); - } - - @Override - public V setValue(V value) { - return e.setValue(value); - } - }; - } - - @Override - public void remove() { - i.remove(); - } - }; - } - - @Override - public boolean contains(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean remove(Object o) { - throw new UnsupportedOperationException(); - } - - @Override - public Spliterator> spliterator() { - throw new UnsupportedOperationException(); - } - - @Override - public void forEach(Consumer> action) { - throw new UnsupportedOperationException(); - } - } - - @Override - public Set> entrySet() { - return new EntrySet(); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/NumUtil.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java similarity index 83% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/NumUtil.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java index 5966c04c6c9..f34ce87ff4f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/NumUtil.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/NumUtil.java @@ -20,10 +20,12 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.asm; +package org.graalvm.compiler.core.common; // JaCoCo Exclude +import jdk.vm.ci.code.CodeUtil; + /** * A collection of static utility functions that check ranges of numbers. */ @@ -183,4 +185,43 @@ public class NumUtil { return 0xFFFFFFFFFFFFFFFFL; } } + + /** + * Get the minimum value representable in a {@code bits} bit signed integer. + */ + public static long minValue(int bits) { + return CodeUtil.minValue(bits); + } + + /** + * Get the maximum value representable in a {@code bits} bit signed integer. + */ + public static long maxValue(int bits) { + return CodeUtil.maxValue(bits); + } + + /** + * Get the maximum value representable in a {@code bits} bit unsigned integer. + */ + public static long maxValueUnsigned(int bits) { + return getNbitNumberLong(bits); + } + + public static long maxUnsigned(long a, long b) { + if (Long.compareUnsigned(a, b) > 0) { + return b; + } + return a; + } + + public static long minUnsigned(long a, long b) { + if (Long.compareUnsigned(a, b) > 0) { + return a; + } + return b; + } + + public static boolean sameSign(long a, long b) { + return a < 0 == b < 0; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/PermanentBailoutException.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java similarity index 97% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/PermanentBailoutException.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java index 52da33abd57..2e2ef19c59c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/PermanentBailoutException.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.common; +package org.graalvm.compiler.core.common; import jdk.vm.ci.code.BailoutException; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/RetryableBailoutException.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java similarity index 93% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/RetryableBailoutException.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java index 61ef7303147..39fc8990bee 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/RetryableBailoutException.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.common; +package org.graalvm.compiler.core.common; import jdk.vm.ci.code.BailoutException; @@ -36,8 +36,8 @@ public class RetryableBailoutException extends BailoutException { super(false, reason); } - public RetryableBailoutException(Throwable cause, String format) { - super(cause, format); + public RetryableBailoutException(Throwable cause, String format, Object... args) { + super(cause, format, args); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/BiDirectionalTraceBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/BiDirectionalTraceBuilder.java index d99cbad7d47..f0ad0133f95 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/BiDirectionalTraceBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/BiDirectionalTraceBuilder.java @@ -31,7 +31,7 @@ import java.util.Deque; import org.graalvm.compiler.core.common.alloc.TraceBuilderResult.TrivialTracePredicate; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; /** @@ -40,8 +40,8 @@ import org.graalvm.compiler.debug.Indent; */ public final class BiDirectionalTraceBuilder { - public static TraceBuilderResult computeTraces(AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { - return new BiDirectionalTraceBuilder(blocks).build(startBlock, blocks, pred); + public static TraceBuilderResult computeTraces(DebugContext debug, AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { + return new BiDirectionalTraceBuilder(blocks).build(debug, startBlock, blocks, pred); } private final Deque> worklist; @@ -69,22 +69,22 @@ public final class BiDirectionalTraceBuilder { } @SuppressWarnings("try") - private TraceBuilderResult build(AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { - try (Indent indent = Debug.logAndIndent("BiDirectionalTraceBuilder: start trace building")) { - ArrayList traces = buildTraces(); + private TraceBuilderResult build(DebugContext debug, AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { + try (Indent indent = debug.logAndIndent("BiDirectionalTraceBuilder: start trace building")) { + ArrayList traces = buildTraces(debug); assert traces.get(0).getBlocks()[0].equals(startBlock) : "The first traces always contains the start block"; - return TraceBuilderResult.create(blocks, traces, blockToTrace, pred); + return TraceBuilderResult.create(debug, blocks, traces, blockToTrace, pred); } } - protected ArrayList buildTraces() { + protected ArrayList buildTraces(DebugContext debug) { ArrayList traces = new ArrayList<>(); // process worklist while (!worklist.isEmpty()) { AbstractBlockBase block = worklist.pollFirst(); assert block != null; if (!processed(block)) { - Trace trace = new Trace(startTrace(block)); + Trace trace = new Trace(startTrace(debug, block)); for (AbstractBlockBase traceBlock : trace.getBlocks()) { blockToTrace[traceBlock.getId()] = trace; } @@ -97,14 +97,16 @@ public final class BiDirectionalTraceBuilder { /** * Build a new trace starting at {@code block}. + * + * @param debug */ @SuppressWarnings("try") - private Collection> startTrace(AbstractBlockBase block) { + private Collection> startTrace(DebugContext debug, AbstractBlockBase block) { ArrayDeque> trace = new ArrayDeque<>(); - try (Indent i = Debug.logAndIndent("StartTrace: %s", block)) { - try (Indent indentFront = Debug.logAndIndent("Head:")) { + try (Indent i = debug.logAndIndent("StartTrace: %s", block)) { + try (Indent indentFront = debug.logAndIndent("Head:")) { for (AbstractBlockBase currentBlock = block; currentBlock != null; currentBlock = selectPredecessor(currentBlock)) { - addBlockToTrace(currentBlock); + addBlockToTrace(debug, currentBlock); trace.addFirst(currentBlock); } } @@ -114,21 +116,21 @@ public final class BiDirectionalTraceBuilder { b.setLinearScanNumber(blockNr++); } - try (Indent indentBack = Debug.logAndIndent("Tail:")) { + try (Indent indentBack = debug.logAndIndent("Tail:")) { for (AbstractBlockBase currentBlock = selectSuccessor(block); currentBlock != null; currentBlock = selectSuccessor(currentBlock)) { - addBlockToTrace(currentBlock); + addBlockToTrace(debug, currentBlock); trace.addLast(currentBlock); /* This time we can number the blocks immediately as we go forwards. */ currentBlock.setLinearScanNumber(blockNr++); } } } - Debug.log("Trace: %s", trace); + debug.log("Trace: %s", trace); return trace; } - private void addBlockToTrace(AbstractBlockBase currentBlock) { - Debug.log("add %s (prob: %f)", currentBlock, currentBlock.probability()); + private void addBlockToTrace(DebugContext debug, AbstractBlockBase currentBlock) { + debug.log("add %s (prob: %f)", currentBlock, currentBlock.probability()); processed.set(currentBlock.getId()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java index 91ff0154db0..4b51e378daa 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java @@ -22,18 +22,16 @@ */ package org.graalvm.compiler.core.common.alloc; -import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure; - -import java.util.HashMap; -import java.util.Map; +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.Register.RegisterCategory; import jdk.vm.ci.code.RegisterArray; import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.meta.PlatformKind; -import org.graalvm.compiler.core.common.GraalOptions; - /** * Configuration for register allocation. This is different to {@link RegisterConfig} as it only * returns registers specified by {@link GraalOptions#RegisterPressure}. @@ -82,11 +80,10 @@ public class RegisterAllocationConfig { } protected RegisterArray initAllocatable(RegisterArray registers) { - if (RegisterPressure.getValue() != null && !RegisterPressure.getValue().equals(ALL_REGISTERS)) { - String[] names = RegisterPressure.getValue().split(","); - Register[] regs = new Register[names.length]; - for (int i = 0; i < names.length; i++) { - regs[i] = findRegister(names[i], registers); + if (allocationRestrictedTo != null) { + Register[] regs = new Register[allocationRestrictedTo.length]; + for (int i = 0; i < allocationRestrictedTo.length; i++) { + regs[i] = findRegister(allocationRestrictedTo[i], registers); } return new RegisterArray(regs); } @@ -95,12 +92,18 @@ public class RegisterAllocationConfig { } protected final RegisterConfig registerConfig; - private final Map categorized = new HashMap<>(); + private final EconomicMap categorized = EconomicMap.create(Equivalence.DEFAULT); + private final String[] allocationRestrictedTo; private RegisterArray cachedRegisters; - public RegisterAllocationConfig(RegisterConfig registerConfig) { + /** + * @param allocationRestrictedTo if not {@code null}, register allocation will be restricted to + * registers whose names appear in this array + */ + public RegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { assert registerConfig != null; this.registerConfig = registerConfig; + this.allocationRestrictedTo = allocationRestrictedTo; } /** @@ -118,6 +121,13 @@ public class RegisterAllocationConfig { return ret; } + /** + * Gets the {@link RegisterCategory} for the given {@link PlatformKind}. + */ + public RegisterCategory getRegisterCategory(PlatformKind kind) { + return getAllocatableRegisters(kind).allocatableRegisters[0].getRegisterCategory(); + } + protected AllocatableRegisters createAllocatableRegisters(RegisterArray registers) { int min = Integer.MAX_VALUE; int max = Integer.MIN_VALUE; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/SingleBlockTraceBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/SingleBlockTraceBuilder.java index 960c3b70df8..caf13edef4d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/SingleBlockTraceBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/SingleBlockTraceBuilder.java @@ -26,17 +26,18 @@ import java.util.ArrayList; import org.graalvm.compiler.core.common.alloc.TraceBuilderResult.TrivialTracePredicate; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; +import org.graalvm.compiler.debug.DebugContext; /** * Builds traces consisting of a single basic block. */ public final class SingleBlockTraceBuilder { - public static TraceBuilderResult computeTraces(AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { - return build(startBlock, blocks, pred); + public static TraceBuilderResult computeTraces(DebugContext debug, AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { + return build(debug, startBlock, blocks, pred); } - private static TraceBuilderResult build(AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { + private static TraceBuilderResult build(DebugContext debug, AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { Trace[] blockToTrace = new Trace[blocks.length]; ArrayList traces = new ArrayList<>(blocks.length); @@ -49,7 +50,7 @@ public final class SingleBlockTraceBuilder { } assert traces.get(0).getBlocks()[0].equals(startBlock) : "The first traces always contains the start block"; - return TraceBuilderResult.create(blocks, traces, blockToTrace, pred); + return TraceBuilderResult.create(debug, blocks, traces, blockToTrace, pred); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceBuilderResult.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceBuilderResult.java index da877f190a0..7fd2b1291db 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceBuilderResult.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceBuilderResult.java @@ -27,7 +27,7 @@ import java.util.Arrays; import java.util.BitSet; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; public final class TraceBuilderResult { @@ -39,9 +39,9 @@ public final class TraceBuilderResult { private final ArrayList traces; private final Trace[] blockToTrace; - static TraceBuilderResult create(AbstractBlockBase[] blocks, ArrayList traces, Trace[] blockToTrace, TrivialTracePredicate pred) { + static TraceBuilderResult create(DebugContext debug, AbstractBlockBase[] blocks, ArrayList traces, Trace[] blockToTrace, TrivialTracePredicate pred) { connect(traces, blockToTrace); - ArrayList newTraces = reorderTraces(traces, pred); + ArrayList newTraces = reorderTraces(debug, traces, pred); TraceBuilderResult traceBuilderResult = new TraceBuilderResult(newTraces, blockToTrace); traceBuilderResult.numberTraces(); assert verify(traceBuilderResult, blocks.length); @@ -157,11 +157,11 @@ public final class TraceBuilderResult { } @SuppressWarnings("try") - private static ArrayList reorderTraces(ArrayList oldTraces, TrivialTracePredicate pred) { + private static ArrayList reorderTraces(DebugContext debug, ArrayList oldTraces, TrivialTracePredicate pred) { if (pred == null) { return oldTraces; } - try (Indent indent = Debug.logAndIndent("ReorderTrace")) { + try (Indent indent = debug.logAndIndent("ReorderTrace")) { ArrayList newTraces = new ArrayList<>(oldTraces.size()); for (int oldTraceIdx = 0; oldTraceIdx < oldTraces.size(); oldTraceIdx++) { Trace currentTrace = oldTraces.get(oldTraceIdx); @@ -171,7 +171,7 @@ public final class TraceBuilderResult { addTrace(newTraces, currentTrace); for (Trace succTrace : currentTrace.getSuccessors()) { if (pred.isTrivialTrace(succTrace) && !alreadyProcessed(newTraces, succTrace)) { - Debug.log("Moving trivial trace from %d to %d", succTrace.getId(), newTraces.size()); + debug.log("Moving trivial trace from %d to %d", succTrace.getId(), newTraces.size()); // add trivial successor trace addTrace(newTraces, succTrace); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceStatisticsPrinter.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceStatisticsPrinter.java index 2e09be8d3a7..6f7d513901a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceStatisticsPrinter.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/TraceStatisticsPrinter.java @@ -25,33 +25,32 @@ package org.graalvm.compiler.core.common.alloc; import java.util.List; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; public final class TraceStatisticsPrinter { private static final String SEP = ";"; @SuppressWarnings("try") - public static void printTraceStatistics(TraceBuilderResult result, String compilationUnitName) { - try (Scope s = Debug.scope("DumpTraceStatistics")) { - if (Debug.isLogEnabled(Debug.VERBOSE_LOG_LEVEL)) { - print(result, compilationUnitName); + public static void printTraceStatistics(DebugContext debug, TraceBuilderResult result, String compilationUnitName) { + try (DebugContext.Scope s = debug.scope("DumpTraceStatistics")) { + if (debug.isLogEnabled(DebugContext.VERBOSE_LEVEL)) { + print(debug, result, compilationUnitName); } } catch (Throwable e) { - Debug.handle(e); + debug.handle(e); } } @SuppressWarnings("try") - protected static void print(TraceBuilderResult result, String compilationUnitName) { + protected static void print(DebugContext debug, TraceBuilderResult result, String compilationUnitName) { List traces = result.getTraces(); int numTraces = traces.size(); - try (Indent indent0 = Debug.logAndIndent(Debug.VERBOSE_LOG_LEVEL, "")) { - Debug.log(Debug.VERBOSE_LOG_LEVEL, "%s", compilationUnitName != null ? compilationUnitName : "null"); - try (Indent indent1 = Debug.logAndIndent(Debug.VERBOSE_LOG_LEVEL, "")) { - printRawLine("tracenumber", "total", "min", "max", "numBlocks"); + try (Indent indent0 = debug.logAndIndent(DebugContext.VERBOSE_LEVEL, "")) { + debug.log(DebugContext.VERBOSE_LEVEL, "%s", compilationUnitName != null ? compilationUnitName : "null"); + try (Indent indent1 = debug.logAndIndent(DebugContext.VERBOSE_LEVEL, "")) { + printRawLine(debug, "tracenumber", "total", "min", "max", "numBlocks"); for (int i = 0; i < numTraces; i++) { AbstractBlockBase[] t = traces.get(i).getBlocks(); double total = 0; @@ -67,20 +66,20 @@ public final class TraceStatisticsPrinter { max = probability; } } - printLine(i, total, min, max, t.length); + printLine(debug, i, total, min, max, t.length); } } - Debug.log(Debug.VERBOSE_LOG_LEVEL, ""); + debug.log(DebugContext.VERBOSE_LEVEL, ""); } - Debug.log(Debug.VERBOSE_LOG_LEVEL, ""); + debug.log(DebugContext.VERBOSE_LEVEL, ""); } - private static void printRawLine(Object tracenr, Object totalTime, Object minProb, Object maxProb, Object numBlocks) { - Debug.log(Debug.VERBOSE_LOG_LEVEL, "%s", String.join(SEP, tracenr.toString(), totalTime.toString(), minProb.toString(), maxProb.toString(), numBlocks.toString())); + private static void printRawLine(DebugContext debug, Object tracenr, Object totalTime, Object minProb, Object maxProb, Object numBlocks) { + debug.log(DebugContext.VERBOSE_LEVEL, "%s", String.join(SEP, tracenr.toString(), totalTime.toString(), minProb.toString(), maxProb.toString(), numBlocks.toString())); } - private static void printLine(int tracenr, double totalTime, double minProb, double maxProb, int numBlocks) { - printRawLine(tracenr, totalTime, minProb, maxProb, numBlocks); + private static void printLine(DebugContext debug, int tracenr, double totalTime, double minProb, double maxProb, int numBlocks) { + printRawLine(debug, tracenr, totalTime, minProb, maxProb, numBlocks); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/UniDirectionalTraceBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/UniDirectionalTraceBuilder.java index 5e238268993..42023e1c007 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/UniDirectionalTraceBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/UniDirectionalTraceBuilder.java @@ -29,7 +29,7 @@ import java.util.PriorityQueue; import org.graalvm.compiler.core.common.alloc.TraceBuilderResult.TrivialTracePredicate; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; /** @@ -37,8 +37,8 @@ import org.graalvm.compiler.debug.Indent; */ public final class UniDirectionalTraceBuilder { - public static TraceBuilderResult computeTraces(AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { - return new UniDirectionalTraceBuilder(blocks).build(startBlock, blocks, pred); + public static TraceBuilderResult computeTraces(DebugContext debug, AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { + return new UniDirectionalTraceBuilder(blocks).build(debug, startBlock, blocks, pred); } private final PriorityQueue> worklist; @@ -71,14 +71,14 @@ public final class UniDirectionalTraceBuilder { } @SuppressWarnings("try") - private TraceBuilderResult build(AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { - try (Indent indent = Debug.logAndIndent("UniDirectionalTraceBuilder: start trace building: %s", startBlock)) { - ArrayList traces = buildTraces(startBlock); - return TraceBuilderResult.create(blocks, traces, blockToTrace, pred); + private TraceBuilderResult build(DebugContext debug, AbstractBlockBase startBlock, AbstractBlockBase[] blocks, TrivialTracePredicate pred) { + try (Indent indent = debug.logAndIndent("UniDirectionalTraceBuilder: start trace building: %s", startBlock)) { + ArrayList traces = buildTraces(debug, startBlock); + return TraceBuilderResult.create(debug, blocks, traces, blockToTrace, pred); } } - protected ArrayList buildTraces(AbstractBlockBase startBlock) { + protected ArrayList buildTraces(DebugContext debug, AbstractBlockBase startBlock) { ArrayList traces = new ArrayList<>(); // add start block worklist.add(startBlock); @@ -87,7 +87,7 @@ public final class UniDirectionalTraceBuilder { AbstractBlockBase block = worklist.poll(); assert block != null; if (!processed(block)) { - Trace trace = new Trace(startTrace(block)); + Trace trace = new Trace(startTrace(debug, block)); for (AbstractBlockBase traceBlock : trace.getBlocks()) { blockToTrace[traceBlock.getId()] = trace; } @@ -102,13 +102,13 @@ public final class UniDirectionalTraceBuilder { * Build a new trace starting at {@code block}. */ @SuppressWarnings("try") - private List> startTrace(AbstractBlockBase block) { + private List> startTrace(DebugContext debug, AbstractBlockBase block) { assert checkPredecessorsProcessed(block); ArrayList> trace = new ArrayList<>(); int blockNumber = 0; - try (Indent i = Debug.logAndIndent("StartTrace: %s", block)) { + try (Indent i = debug.logAndIndent("StartTrace: %s", block)) { for (AbstractBlockBase currentBlock = block; currentBlock != null; currentBlock = selectNext(currentBlock)) { - Debug.log("add %s (prob: %f)", currentBlock, currentBlock.probability()); + debug.log("add %s (prob: %f)", currentBlock, currentBlock.probability()); processed.set(currentBlock.getId()); trace.add(currentBlock); unblock(currentBlock); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java index 546dbd0dc11..6b1f94926b6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/calc/Condition.java @@ -343,116 +343,7 @@ public enum Condition { if (lt instanceof PrimitiveConstant) { PrimitiveConstant lp = (PrimitiveConstant) lt; PrimitiveConstant rp = (PrimitiveConstant) rt; - switch (lp.getJavaKind()) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: { - int x = lp.asInt(); - int y = rp.asInt(); - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - case AE: - return UnsignedMath.aboveOrEqual(x, y); - case BE: - return UnsignedMath.belowOrEqual(x, y); - case AT: - return UnsignedMath.aboveThan(x, y); - case BT: - return UnsignedMath.belowThan(x, y); - default: - throw new GraalError("expected condition: %s", this); - } - } - case Long: { - long x = lp.asLong(); - long y = rp.asLong(); - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - case AE: - return UnsignedMath.aboveOrEqual(x, y); - case BE: - return UnsignedMath.belowOrEqual(x, y); - case AT: - return UnsignedMath.aboveThan(x, y); - case BT: - return UnsignedMath.belowThan(x, y); - default: - throw new GraalError("expected condition: %s", this); - } - } - case Float: { - float x = lp.asFloat(); - float y = rp.asFloat(); - if (Float.isNaN(x) || Float.isNaN(y)) { - return unorderedIsTrue; - } - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - default: - throw new GraalError("expected condition: %s", this); - } - } - case Double: { - double x = lp.asDouble(); - double y = rp.asDouble(); - if (Double.isNaN(x) || Double.isNaN(y)) { - return unorderedIsTrue; - } - switch (this) { - case EQ: - return x == y; - case NE: - return x != y; - case LT: - return x < y; - case LE: - return x <= y; - case GT: - return x > y; - case GE: - return x >= y; - default: - throw new GraalError("expected condition: %s", this); - } - } - default: - throw new GraalError("expected value kind %s while folding condition: %s", lp.getJavaKind(), this); - } + return foldCondition(lp, rp, unorderedIsTrue); } else { Boolean equal = constantReflection.constantEquals(lt, rt); if (equal == null) { @@ -469,6 +360,128 @@ public enum Condition { } } + /** + * Attempts to fold a comparison between two primitive constants and return the result. + * + * @param lp the constant on the left side of the comparison + * @param rp the constant on the right side of the comparison + * @param unorderedIsTrue true if an undecided float comparison should result in "true" + * @return true if the comparison is known to be true, false if the comparison is known to be + * false + */ + public boolean foldCondition(PrimitiveConstant lp, PrimitiveConstant rp, boolean unorderedIsTrue) { + switch (lp.getJavaKind()) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: { + int x = lp.asInt(); + int y = rp.asInt(); + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + case AE: + return UnsignedMath.aboveOrEqual(x, y); + case BE: + return UnsignedMath.belowOrEqual(x, y); + case AT: + return UnsignedMath.aboveThan(x, y); + case BT: + return UnsignedMath.belowThan(x, y); + default: + throw new GraalError("expected condition: %s", this); + } + } + case Long: { + long x = lp.asLong(); + long y = rp.asLong(); + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + case AE: + return UnsignedMath.aboveOrEqual(x, y); + case BE: + return UnsignedMath.belowOrEqual(x, y); + case AT: + return UnsignedMath.aboveThan(x, y); + case BT: + return UnsignedMath.belowThan(x, y); + default: + throw new GraalError("expected condition: %s", this); + } + } + case Float: { + float x = lp.asFloat(); + float y = rp.asFloat(); + if (Float.isNaN(x) || Float.isNaN(y)) { + return unorderedIsTrue; + } + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + default: + throw new GraalError("expected condition: %s", this); + } + } + case Double: { + double x = lp.asDouble(); + double y = rp.asDouble(); + if (Double.isNaN(x) || Double.isNaN(y)) { + return unorderedIsTrue; + } + switch (this) { + case EQ: + return x == y; + case NE: + return x != y; + case LT: + return x < y; + case LE: + return x <= y; + case GT: + return x > y; + case GE: + return x >= y; + default: + throw new GraalError("expected condition: %s", this); + } + } + default: + throw new GraalError("expected value kind %s while folding condition: %s", lp.getJavaKind(), this); + } + } + public Condition join(Condition other) { if (other == this) { return this; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java index a1d2661e71b..bc2627ebb5e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractBlockBase.java @@ -22,9 +22,6 @@ */ package org.graalvm.compiler.core.common.cfg; -import java.util.Collections; -import java.util.List; - public abstract class AbstractBlockBase> { protected int id; @@ -34,7 +31,8 @@ public abstract class AbstractBlockBase> { protected T[] successors; private T dominator; - private List dominated; + private T firstDominated; + private T dominatedSibling; private int domNumber; private int maxChildDomNumber; @@ -97,19 +95,27 @@ public abstract class AbstractBlockBase> { this.domDepth = dominator.domDepth + 1; } + /** + * Level in the dominator tree starting with 0 for the start block. + */ public int getDominatorDepth() { return domDepth; } - public List getDominated() { - if (dominated == null) { - return Collections.emptyList(); - } - return dominated; + public T getFirstDominated() { + return this.firstDominated; } - public void setDominated(List blocks) { - dominated = blocks; + public void setFirstDominated(T block) { + this.firstDominated = block; + } + + public T getDominatedSibling() { + return this.dominatedSibling; + } + + public void setDominatedSibling(T block) { + this.dominatedSibling = block; } @Override @@ -158,4 +164,9 @@ public abstract class AbstractBlockBase> { public abstract double probability(); public abstract T getDominator(int distance); + + @Override + public int hashCode() { + return id; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java index ccc46e4e4e8..5b81652d5a2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/AbstractControlFlowGraph.java @@ -81,6 +81,8 @@ public interface AbstractControlFlowGraph> { return b; } else if (b == null) { return a; + } else if (a == b) { + return a; } else { int aDomDepth = a.getDominatorDepth(); int bDomDepth = b.getDominatorDepth(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java index ec9a55f4bca..cac5c9f7b33 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/CFGVerifier.java @@ -45,11 +45,22 @@ public class CFGVerifier { if (block.getDominator() != null) { assert block.getDominator().getId() < block.getId(); - assert block.getDominator().getDominated().contains(block); + + AbstractBlockBase domChild = block.getDominator().getFirstDominated(); + while (domChild != null) { + if (domChild == block) { + break; + } + domChild = domChild.getDominatedSibling(); + } + assert domChild != null : "dominators must contain block"; } - for (T dominated : block.getDominated()) { + + T dominated = block.getFirstDominated(); + while (dominated != null) { assert dominated.getId() > block.getId(); assert dominated.getDominator() == block; + dominated = dominated.getDominatedSibling(); } T postDominatorBlock = block.getPostdominator(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java index 41d884addd5..af3cb75d9b6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/cfg/Loop.java @@ -87,6 +87,10 @@ public abstract class Loop> { return exits; } + public void addExit(T t) { + exits.add(t); + } + /** * Determines if one loop is a transitive parent of another loop. * @@ -105,4 +109,9 @@ public abstract class Loop> { } return false; } + + @Override + public int hashCode() { + return index + depth * 31; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ConstantFieldProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ConstantFieldProvider.java index 2cc96bcd43d..3327d9f1238 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ConstantFieldProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ConstantFieldProvider.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.core.common.spi; +import org.graalvm.compiler.options.OptionValues; + import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.ResolvedJavaField; @@ -32,6 +34,8 @@ public interface ConstantFieldProvider { public interface ConstantFieldTool { + OptionValues getOptions(); + JavaConstant readValue(); JavaConstant getReceiver(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java index 58890ea9db6..63f2bfb203f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java @@ -23,7 +23,7 @@ package org.graalvm.compiler.core.common.spi; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.LocationIdentity; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.ValueKindFactory; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java index ae40986bd5c..c6dfab4540a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/JavaConstantFieldProvider.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.core.common.spi; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaType; @@ -39,7 +39,7 @@ public abstract class JavaConstantFieldProvider implements ConstantFieldProvider static class Options { @Option(help = "Determines whether to treat final fields with default values as constant.")// - public static final OptionValue TrustFinalDefaultFields = new OptionValue<>(true); + public static final OptionKey TrustFinalDefaultFields = new OptionKey<>(true); } protected JavaConstantFieldProvider(MetaAccessProvider metaAccess) { @@ -93,7 +93,7 @@ public abstract class JavaConstantFieldProvider implements ConstantFieldProvider @SuppressWarnings("unused") protected boolean isFinalFieldValueConstant(ResolvedJavaField field, JavaConstant value, ConstantFieldTool tool) { - return !value.isDefaultForKind() || Options.TrustFinalDefaultFields.getValue(); + return !value.isDefaultForKind() || Options.TrustFinalDefaultFields.getValue(tool.getOptions()); } @SuppressWarnings("unused") @@ -104,7 +104,7 @@ public abstract class JavaConstantFieldProvider implements ConstantFieldProvider if (isWellKnownImplicitStableField(field)) { return true; } - if (field == stringHashField) { + if (field.equals(stringHashField)) { return true; } return false; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/LIRKindTool.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/LIRKindTool.java index 9a4015476bf..a74c96ad17b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/LIRKindTool.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/LIRKindTool.java @@ -48,4 +48,14 @@ public interface LIRKindTool { * Get the architecture specific kind pointer-sized integer kind. */ LIRKind getWordKind(); + + /** + * Get the platform specific kind used to represent compressed oops. + */ + LIRKind getNarrowOopKind(); + + /** + * Gets the platform specific kind used to represent compressed metaspace pointers. + */ + LIRKind getNarrowPointerKind(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java index 7debe2c12ea..a8cf097051f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/AbstractPointerStamp.java @@ -59,8 +59,8 @@ public abstract class AbstractPointerStamp extends Stamp { return result; } - @Override - public Stamp join(Stamp stamp) { + protected Stamp defaultPointerJoin(Stamp stamp) { + assert getClass() == stamp.getClass(); AbstractPointerStamp other = (AbstractPointerStamp) stamp; boolean joinNonNull = this.nonNull || other.nonNull; boolean joinAlwaysNull = this.alwaysNull || other.alwaysNull; @@ -89,6 +89,42 @@ public abstract class AbstractPointerStamp extends Stamp { return copyWith(false, false); } + public static Stamp pointerNonNull(Stamp stamp) { + AbstractPointerStamp pointer = (AbstractPointerStamp) stamp; + return pointer.asNonNull(); + } + + public static Stamp pointerMaybeNull(Stamp stamp) { + AbstractPointerStamp pointer = (AbstractPointerStamp) stamp; + return pointer.asMaybeNull(); + } + + public static Stamp pointerAlwaysNull(Stamp stamp) { + AbstractPointerStamp pointer = (AbstractPointerStamp) stamp; + return pointer.asAlwaysNull(); + } + + public Stamp asNonNull() { + if (isEmpty()) { + return this; + } + return copyWith(true, false); + } + + public Stamp asMaybeNull() { + if (isEmpty()) { + return this; + } + return copyWith(false, false); + } + + public Stamp asAlwaysNull() { + if (isEmpty()) { + return this; + } + return copyWith(false, true); + } + @Override public boolean equals(Object obj) { if (this == obj) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java index af71cb1964f..5bd75e637c0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticOpTable.java @@ -27,11 +27,6 @@ import static jdk.vm.ci.meta.MetaUtil.getSimpleName; import java.util.Arrays; import java.util.Objects; import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaKind; import org.graalvm.compiler.core.common.calc.FloatConvert; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Add; @@ -52,6 +47,10 @@ import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Abs; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Neg; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Not; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Sqrt; +import org.graalvm.util.CollectionsUtil; + +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaKind; /** * Information about arithmetic operations. @@ -95,12 +94,6 @@ public final class ArithmeticOpTable { public static final ArithmeticOpTable EMPTY = new ArithmeticOpTable(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); - public ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp
    div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, - BinaryOp xor, ShiftOp shl, ShiftOp shr, ShiftOp ushr, UnaryOp abs, UnaryOp sqrt, IntegerConvertOp zeroExtend, - IntegerConvertOp signExtend, IntegerConvertOp narrow, FloatConvertOp... floatConvert) { - this(neg, add, sub, mul, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow, Stream.of(floatConvert)); - } - public interface ArithmeticOpWrapper { UnaryOp wrapUnaryOp(UnaryOp op); @@ -147,14 +140,13 @@ public final class ArithmeticOpTable { IntegerConvertOp signExtend = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getSignExtend()); IntegerConvertOp narrow = wrapIfNonNull(wrapper::wrapIntegerConvertOp, inner.getNarrow()); - Stream floatConvert = Stream.of(inner.floatConvert).filter(Objects::nonNull).map(wrapper::wrapFloatConvertOp); - + FloatConvertOp[] floatConvert = CollectionsUtil.filterAndMapToArray(inner.floatConvert, Objects::nonNull, wrapper::wrapFloatConvertOp, FloatConvertOp[]::new); return new ArithmeticOpTable(neg, add, sub, mul, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow, floatConvert); } - private ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp
    div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, + protected ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp
    div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, BinaryOp xor, ShiftOp shl, ShiftOp shr, ShiftOp ushr, UnaryOp abs, UnaryOp sqrt, IntegerConvertOp zeroExtend, - IntegerConvertOp signExtend, IntegerConvertOp narrow, Stream floatConvert) { + IntegerConvertOp signExtend, IntegerConvertOp narrow, FloatConvertOp... floatConvert) { this.neg = neg; this.add = add; this.sub = sub; @@ -174,7 +166,9 @@ public final class ArithmeticOpTable { this.signExtend = signExtend; this.narrow = narrow; this.floatConvert = new FloatConvertOp[FloatConvert.values().length]; - floatConvert.forEach(op -> this.floatConvert[op.getFloatConvert().ordinal()] = op); + for (FloatConvertOp op : floatConvert) { + this.floatConvert[op.getFloatConvert().ordinal()] = op; + } this.hash = Objects.hash(neg, add, sub, mul, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow); } @@ -318,7 +312,7 @@ public final class ArithmeticOpTable { } public static String toString(Op... ops) { - return Arrays.asList(ops).stream().map(o -> o == null ? "null" : o.operator + "{" + getSimpleName(o.getClass(), false) + "}").collect(Collectors.joining(",")); + return CollectionsUtil.mapAndJoin(ops, o -> o == null ? "null" : o.operator + "{" + getSimpleName(o.getClass(), false) + "}", ","); } private boolean opsEquals(ArithmeticOpTable that) { @@ -742,6 +736,11 @@ public final class ArithmeticOpTable { protected Narrow() { super("Narrow"); } + + @Override + public Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp) { + return null; + } } protected IntegerConvertOp(String op) { @@ -755,5 +754,10 @@ public final class ArithmeticOpTable { public IntegerConvertOp unwrap() { return this; } + + /** + * Computes the stamp of the input for the given output stamp. + */ + public abstract Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticStamp.java index ee0979f6d16..cb3ee14aa91 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ArithmeticStamp.java @@ -46,7 +46,11 @@ public abstract class ArithmeticStamp extends Stamp { @Override public Stamp improveWith(Stamp other) { - return this.join(other); + if (this.isCompatible(other)) { + return this.join(other); + } + // Cannot improve, because stamps are not compatible. + return this; } @Override @@ -65,7 +69,7 @@ public abstract class ArithmeticStamp extends Stamp { if (!(obj instanceof ArithmeticStamp)) { return false; } - assert Objects.equals(ops, ((ArithmeticStamp) obj).ops); + assert Objects.equals(ops, ((ArithmeticStamp) obj).ops) : ops + " vs. " + ((ArithmeticStamp) obj).ops; return true; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java index c55efe65a00..602feebb411 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/FloatStamp.java @@ -154,6 +154,7 @@ public class FloatStamp extends PrimitiveStamp { return Double.isNaN(lowerBound); } + @Override public boolean isUnrestricted() { return lowerBound == Double.NEGATIVE_INFINITY && upperBound == Double.POSITIVE_INFINITY && !nonNaN; } @@ -301,10 +302,6 @@ public class FloatStamp extends PrimitiveStamp { return null; } - public boolean isConstant() { - return (nonNaN && Double.compare(lowerBound, upperBound) == 0); - } - private static final ArithmeticOpTable OPS = new ArithmeticOpTable( new UnaryOp.Neg() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java index b142e2c6d32..f41e7a34012 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IllegalStamp.java @@ -58,6 +58,11 @@ public final class IllegalStamp extends Stamp { return this; } + @Override + public boolean isUnrestricted() { + return true; + } + @Override public Stamp empty() { return this; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java index c76198db83d..c9fb891f453 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/IntegerStamp.java @@ -31,6 +31,7 @@ import java.nio.ByteBuffer; import java.util.Formatter; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp; import org.graalvm.compiler.core.common.type.ArithmeticOpTable.FloatConvertOp; @@ -54,41 +55,101 @@ import jdk.vm.ci.meta.SerializableConstant; * The description consists of (inclusive) lower and upper bounds and up (may be set) and down * (always set) bit-masks. */ -public class IntegerStamp extends PrimitiveStamp { +public final class IntegerStamp extends PrimitiveStamp { private final long lowerBound; private final long upperBound; private final long downMask; private final long upMask; - public IntegerStamp(int bits, long lowerBound, long upperBound, long downMask, long upMask) { + private IntegerStamp(int bits, long lowerBound, long upperBound, long downMask, long upMask) { super(bits, OPS); + this.lowerBound = lowerBound; this.upperBound = upperBound; this.downMask = downMask; this.upMask = upMask; + assert lowerBound >= CodeUtil.minValue(bits) : this; assert upperBound <= CodeUtil.maxValue(bits) : this; assert (downMask & CodeUtil.mask(bits)) == downMask : this; assert (upMask & CodeUtil.mask(bits)) == upMask : this; } - public static IntegerStamp stampForMask(int bits, long downMask, long upMask) { - long lowerBound; - long upperBound; - if (((upMask >>> (bits - 1)) & 1) == 0) { - lowerBound = downMask; - upperBound = upMask; - } else if (((downMask >>> (bits - 1)) & 1) == 1) { - lowerBound = downMask; - upperBound = upMask; + public static IntegerStamp create(int bits, long lowerBoundInput, long upperBoundInput) { + return create(bits, lowerBoundInput, upperBoundInput, 0, CodeUtil.mask(bits)); + } + + public static IntegerStamp create(int bits, long lowerBoundInput, long upperBoundInput, long downMask, long upMask) { + assert (downMask & ~upMask) == 0 : String.format("\u21ca: %016x \u21c8: %016x", downMask, upMask); + + // Set lower bound, use masks to make it more precise + long minValue = minValueForMasks(bits, downMask, upMask); + long lowerBoundTmp = Math.max(lowerBoundInput, minValue); + + // Set upper bound, use masks to make it more precise + long maxValue = maxValueForMasks(bits, downMask, upMask); + long upperBoundTmp = Math.min(upperBoundInput, maxValue); + + // Assign masks now with the bounds in mind. + final long boundedDownMask; + final long boundedUpMask; + long defaultMask = CodeUtil.mask(bits); + if (lowerBoundTmp == upperBoundTmp) { + boundedDownMask = lowerBoundTmp; + boundedUpMask = lowerBoundTmp; + } else if (lowerBoundTmp >= 0) { + int upperBoundLeadingZeros = Long.numberOfLeadingZeros(upperBoundTmp); + long differentBits = lowerBoundTmp ^ upperBoundTmp; + int sameBitCount = Long.numberOfLeadingZeros(differentBits << upperBoundLeadingZeros); + + boundedUpMask = upperBoundTmp | -1L >>> (upperBoundLeadingZeros + sameBitCount); + boundedDownMask = upperBoundTmp & ~(-1L >>> (upperBoundLeadingZeros + sameBitCount)); } else { - lowerBound = downMask | (-1L << (bits - 1)); - upperBound = CodeUtil.maxValue(bits) & upMask; + if (upperBoundTmp >= 0) { + boundedUpMask = defaultMask; + boundedDownMask = 0; + } else { + int lowerBoundLeadingOnes = Long.numberOfLeadingZeros(~lowerBoundTmp); + long differentBits = lowerBoundTmp ^ upperBoundTmp; + int sameBitCount = Long.numberOfLeadingZeros(differentBits << lowerBoundLeadingOnes); + + boundedUpMask = lowerBoundTmp | -1L >>> (lowerBoundLeadingOnes + sameBitCount) | ~(-1L >>> lowerBoundLeadingOnes); + boundedDownMask = lowerBoundTmp & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes); + } } - lowerBound = CodeUtil.convert(lowerBound, bits, false); - upperBound = CodeUtil.convert(upperBound, bits, false); - return new IntegerStamp(bits, lowerBound, upperBound, downMask, upMask); + + return new IntegerStamp(bits, lowerBoundTmp, upperBoundTmp, defaultMask & (downMask | boundedDownMask), defaultMask & upMask & boundedUpMask); + } + + static long significantBit(long bits, long value) { + return (value >>> (bits - 1)) & 1; + } + + static long minValueForMasks(int bits, long downMask, long upMask) { + if (significantBit(bits, upMask) == 0) { + // Value is always positive. Minimum value always positive. + assert significantBit(bits, downMask) == 0; + return downMask; + } else { + // Value can be positive or negative. Minimum value always negative. + return downMask | (-1L << (bits - 1)); + } + } + + static long maxValueForMasks(int bits, long downMask, long upMask) { + if (significantBit(bits, downMask) == 1) { + // Value is always negative. Maximum value always negative. + assert significantBit(bits, upMask) == 1; + return CodeUtil.signExtend(upMask, bits); + } else { + // Value can be positive or negative. Maximum value always positive. + return upMask & (CodeUtil.mask(bits) >>> 1); + } + } + + public static IntegerStamp stampForMask(int bits, long downMask, long upMask) { + return new IntegerStamp(bits, minValueForMasks(bits, downMask, upMask), maxValueForMasks(bits, downMask, upMask), downMask, upMask); } @Override @@ -97,7 +158,7 @@ public class IntegerStamp extends PrimitiveStamp { } @Override - public Stamp empty() { + public IntegerStamp empty() { return new IntegerStamp(getBits(), CodeUtil.maxValue(getBits()), CodeUtil.minValue(getBits()), CodeUtil.mask(getBits()), 0); } @@ -193,6 +254,7 @@ public class IntegerStamp extends PrimitiveStamp { return upMask; } + @Override public boolean isUnrestricted() { return lowerBound == CodeUtil.minValue(getBits()) && upperBound == CodeUtil.maxValue(getBits()) && downMask == 0 && upMask == CodeUtil.mask(getBits()); } @@ -230,23 +292,27 @@ public class IntegerStamp extends PrimitiveStamp { StringBuilder str = new StringBuilder(); str.append('i'); str.append(getBits()); - if (lowerBound == upperBound) { - str.append(" [").append(lowerBound).append(']'); - } else if (lowerBound != CodeUtil.minValue(getBits()) || upperBound != CodeUtil.maxValue(getBits())) { - str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); - } - if (downMask != 0) { - str.append(" \u21ca"); - new Formatter(str).format("%016x", downMask); - } - if (upMask != CodeUtil.mask(getBits())) { - str.append(" \u21c8"); - new Formatter(str).format("%016x", upMask); + if (hasValues()) { + if (lowerBound == upperBound) { + str.append(" [").append(lowerBound).append(']'); + } else if (lowerBound != CodeUtil.minValue(getBits()) || upperBound != CodeUtil.maxValue(getBits())) { + str.append(" [").append(lowerBound).append(" - ").append(upperBound).append(']'); + } + if (downMask != 0) { + str.append(" \u21ca"); + new Formatter(str).format("%016x", downMask); + } + if (upMask != CodeUtil.mask(getBits())) { + str.append(" \u21c8"); + new Formatter(str).format("%016x", upMask); + } + } else { + str.append(""); } return str.toString(); } - private Stamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) { + private IntegerStamp createStamp(IntegerStamp other, long newUpperBound, long newLowerBound, long newDownMask, long newUpMask) { assert getBits() == other.getBits(); if (newLowerBound > newUpperBound || (newDownMask & (~newUpMask)) != 0 || (newUpMask == 0 && (newLowerBound > 0 || newUpperBound < 0))) { return empty(); @@ -255,7 +321,7 @@ public class IntegerStamp extends PrimitiveStamp { } else if (newLowerBound == other.lowerBound && newUpperBound == other.upperBound && newDownMask == other.downMask && newUpMask == other.upMask) { return other; } else { - return new IntegerStamp(getBits(), newLowerBound, newUpperBound, newDownMask, newUpMask); + return IntegerStamp.create(getBits(), newLowerBound, newUpperBound, newDownMask, newUpMask); } } @@ -269,17 +335,16 @@ public class IntegerStamp extends PrimitiveStamp { } @Override - public Stamp join(Stamp otherStamp) { + public IntegerStamp join(Stamp otherStamp) { if (otherStamp == this) { return this; } IntegerStamp other = (IntegerStamp) otherStamp; long newDownMask = downMask | other.downMask; - long newLowerBound = Math.max(lowerBound, other.lowerBound) | newDownMask; + long newLowerBound = Math.max(lowerBound, other.lowerBound); long newUpperBound = Math.min(upperBound, other.upperBound); long newUpMask = upMask & other.upMask; - IntegerStamp limit = StampFactory.forInteger(getBits(), newLowerBound, newUpperBound); - return createStamp(other, newUpperBound, newLowerBound, limit.downMask() | newDownMask, limit.upMask() & newUpMask); + return createStamp(other, newUpperBound, newLowerBound, newDownMask, newUpMask); } @Override @@ -303,6 +368,24 @@ public class IntegerStamp extends PrimitiveStamp { return false; } + public long unsignedUpperBound() { + if (sameSignBounds()) { + return CodeUtil.zeroExtend(upperBound(), getBits()); + } + return NumUtil.maxValueUnsigned(getBits()); + } + + public long unsignedLowerBound() { + if (sameSignBounds()) { + return CodeUtil.zeroExtend(lowerBound(), getBits()); + } + return 0; + } + + private boolean sameSignBounds() { + return NumUtil.sameSign(lowerBound, upperBound); + } + @Override public int hashCode() { final int prime = 31; @@ -369,6 +452,13 @@ public class IntegerStamp extends PrimitiveStamp { return null; } + public static boolean addCanOverflow(IntegerStamp a, IntegerStamp b) { + assert a.getBits() == b.getBits(); + return addOverflowsPositively(a.upperBound(), b.upperBound(), a.getBits()) || + addOverflowsNegatively(a.lowerBound(), b.lowerBound(), a.getBits()); + + } + public static boolean addOverflowsPositively(long x, long y, int bits) { long result = x + y; if (bits == 64) { @@ -430,15 +520,59 @@ public class IntegerStamp extends PrimitiveStamp { } } + public static boolean multiplicationCanOverflow(IntegerStamp a, IntegerStamp b) { + // see IntegerStamp#foldStamp for details + assert a.getBits() == b.getBits(); + if (a.upMask() == 0) { + return false; + } else if (b.upMask() == 0) { + return false; + } + if (a.isUnrestricted()) { + return true; + } + if (b.isUnrestricted()) { + return true; + } + int bits = a.getBits(); + long minNegA = a.lowerBound(); + long maxNegA = Math.min(0, a.upperBound()); + long minPosA = Math.max(0, a.lowerBound()); + long maxPosA = a.upperBound(); + + long minNegB = b.lowerBound(); + long maxNegB = Math.min(0, b.upperBound()); + long minPosB = Math.max(0, b.lowerBound()); + long maxPosB = b.upperBound(); + + boolean mayOverflow = false; + if (a.canBePositive()) { + if (b.canBePositive()) { + mayOverflow |= IntegerStamp.multiplicationOverflows(maxPosA, maxPosB, bits); + mayOverflow |= IntegerStamp.multiplicationOverflows(minPosA, minPosB, bits); + } + if (b.canBeNegative()) { + mayOverflow |= IntegerStamp.multiplicationOverflows(minPosA, maxNegB, bits); + mayOverflow |= IntegerStamp.multiplicationOverflows(maxPosA, minNegB, bits); + + } + } + if (a.canBeNegative()) { + if (b.canBePositive()) { + mayOverflow |= IntegerStamp.multiplicationOverflows(maxNegA, minPosB, bits); + mayOverflow |= IntegerStamp.multiplicationOverflows(minNegA, maxPosB, bits); + } + if (b.canBeNegative()) { + mayOverflow |= IntegerStamp.multiplicationOverflows(minNegA, minNegB, bits); + mayOverflow |= IntegerStamp.multiplicationOverflows(maxNegA, maxNegB, bits); + } + } + return mayOverflow; + } + public static boolean subtractionCanOverflow(IntegerStamp x, IntegerStamp y) { assert x.getBits() == y.getBits(); - // Checkstyle: stop - long x_l = x.lowerBound(); - long x_h = x.upperBound(); - long y_l = y.lowerBound(); - long y_h = y.upperBound(); - // Checkstyle: resume - return subtractionOverflows(x_l, y_h, x.getBits()) || subtractionOverflows(x_h, y_l, x.getBits()); + return subtractionOverflows(x.lowerBound(), y.upperBound(), x.getBits()) || subtractionOverflows(x.upperBound(), y.lowerBound(), x.getBits()); } public static boolean subtractionOverflows(long x, long y, int bits) { @@ -618,7 +752,7 @@ public class IntegerStamp extends PrimitiveStamp { * upper bound after multiplication. * * For example if we consider two stamps a & b that both contain - * negative and positive values, the product of minN_a * minN_b + * negative and positive values, the product of minNegA * minNegB * (both the smallest negative value for each stamp) can only be the * highest positive number. The other candidates can be computed in * a similar fashion. Some of them can never be a new minimum or @@ -627,87 +761,86 @@ public class IntegerStamp extends PrimitiveStamp { * * @formatter:off * - * [x..........0..........y] - * ------------------------- - * [minN maxN minP maxP] - * where maxN = min(0,y) && minP = max(0,x) + * [x................0................y] + * ------------------------------------- + * [minNeg maxNeg minPos maxPos] + * + * where maxNeg = min(0,y) && minPos = max(0,x) * * - * |minN_a maxN_a minP_a maxP_a - * _______|________________________________ - * minN_b |MAX / : / MIN - * maxN_b | / MIN : MAX / - * |---------------+---------------- - * minP_b | / MAX : MIN / - * maxP_b |MIN / : / MAX + * |minNegA maxNegA minPosA maxPosA + * _______ |____________________________________ + * minNegB | MAX / : / MIN + * maxNegB | / MIN : MAX / + * |------------------+----------------- + * minPosB | / MAX : MIN / + * maxPosB | MIN / : / MAX * * @formatter:on */ // We materialize all factors here. If they are needed, the signs of // the stamp will ensure the correct value is used. - // Checkstyle: stop - long minN_a = a.lowerBound(); - long maxN_a = Math.min(0, a.upperBound()); - long minP_a = Math.max(0, a.lowerBound()); - long maxP_a = a.upperBound(); + long minNegA = a.lowerBound(); + long maxNegA = Math.min(0, a.upperBound()); + long minPosA = Math.max(0, a.lowerBound()); + long maxPosA = a.upperBound(); - long minN_b = b.lowerBound(); - long maxN_b = Math.min(0, b.upperBound()); - long minP_b = Math.max(0, b.lowerBound()); - long maxP_b = b.upperBound(); - // Checkstyle: resume + long minNegB = b.lowerBound(); + long maxNegB = Math.min(0, b.upperBound()); + long minPosB = Math.max(0, b.lowerBound()); + long maxPosB = b.upperBound(); // multiplication has shift semantics long newUpMask = ~CodeUtil.mask(Long.numberOfTrailingZeros(a.upMask) + Long.numberOfTrailingZeros(b.upMask)) & CodeUtil.mask(bits); if (a.canBePositive()) { if (b.canBePositive()) { - if (multiplicationOverflows(maxP_a, maxP_b, bits)) { + if (multiplicationOverflows(maxPosA, maxPosB, bits)) { return a.unrestricted(); } - long maxCandidate = maxP_a * maxP_b; - if (multiplicationOverflows(minP_a, minP_b, bits)) { + long maxCandidate = maxPosA * maxPosB; + if (multiplicationOverflows(minPosA, minPosB, bits)) { return a.unrestricted(); } - long minCandidate = minP_a * minP_b; + long minCandidate = minPosA * minPosB; newLowerBound = Math.min(newLowerBound, minCandidate); newUpperBound = Math.max(newUpperBound, maxCandidate); } if (b.canBeNegative()) { - if (multiplicationOverflows(minP_a, maxN_b, bits)) { + if (multiplicationOverflows(minPosA, maxNegB, bits)) { return a.unrestricted(); } - long maxCandidate = minP_a * maxN_b; - if (multiplicationOverflows(maxP_a, minN_b, bits)) { + long maxCandidate = minPosA * maxNegB; + if (multiplicationOverflows(maxPosA, minNegB, bits)) { return a.unrestricted(); } - long minCandidate = maxP_a * minN_b; + long minCandidate = maxPosA * minNegB; newLowerBound = Math.min(newLowerBound, minCandidate); newUpperBound = Math.max(newUpperBound, maxCandidate); } } if (a.canBeNegative()) { if (b.canBePositive()) { - if (multiplicationOverflows(maxN_a, minP_b, bits)) { + if (multiplicationOverflows(maxNegA, minPosB, bits)) { return a.unrestricted(); } - long maxCandidate = maxN_a * minP_b; - if (multiplicationOverflows(minN_a, maxP_b, bits)) { + long maxCandidate = maxNegA * minPosB; + if (multiplicationOverflows(minNegA, maxPosB, bits)) { return a.unrestricted(); } - long minCandidate = minN_a * maxP_b; + long minCandidate = minNegA * maxPosB; newLowerBound = Math.min(newLowerBound, minCandidate); newUpperBound = Math.max(newUpperBound, maxCandidate); } if (b.canBeNegative()) { - if (multiplicationOverflows(minN_a, minN_b, bits)) { + if (multiplicationOverflows(minNegA, minNegB, bits)) { return a.unrestricted(); } - long maxCandidate = minN_a * minN_b; - if (multiplicationOverflows(maxN_a, maxN_b, bits)) { + long maxCandidate = minNegA * minNegB; + if (multiplicationOverflows(maxNegA, maxNegB, bits)) { return a.unrestricted(); } - long minCandidate = maxN_a * maxN_b; + long minCandidate = maxNegA * maxNegB; newLowerBound = Math.min(newLowerBound, minCandidate); newUpperBound = Math.max(newUpperBound, maxCandidate); } @@ -1083,22 +1216,28 @@ public class IntegerStamp extends PrimitiveStamp { assert inputBits == stamp.getBits(); assert inputBits <= resultBits; - long downMask = CodeUtil.zeroExtend(stamp.downMask(), inputBits); - long upMask = CodeUtil.zeroExtend(stamp.upMask(), inputBits); - - if (stamp.lowerBound() < 0 && stamp.upperBound() >= 0) { - /* signed range including 0 and -1 */ - /* - * after sign extension, the whole range from 0 to MAX_INT is - * possible - */ - return IntegerStamp.stampForMask(resultBits, downMask, upMask); + if (inputBits == resultBits) { + return input; } - long lowerBound = CodeUtil.zeroExtend(stamp.lowerBound(), inputBits); - long upperBound = CodeUtil.zeroExtend(stamp.upperBound(), inputBits); + if (input.isEmpty()) { + return StampFactory.forInteger(resultBits).empty(); + } - return new IntegerStamp(resultBits, lowerBound, upperBound, downMask, upMask); + long downMask = CodeUtil.zeroExtend(stamp.downMask(), inputBits); + long upMask = CodeUtil.zeroExtend(stamp.upMask(), inputBits); + long lowerBound = stamp.unsignedLowerBound(); + long upperBound = stamp.unsignedUpperBound(); + return IntegerStamp.create(resultBits, lowerBound, upperBound, downMask, upMask); + } + + @Override + public Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp) { + IntegerStamp stamp = (IntegerStamp) outStamp; + if (stamp.isEmpty()) { + return StampFactory.forInteger(inputBits).empty(); + } + return StampFactory.forUnsignedInteger(inputBits, stamp.lowerBound(), stamp.upperBound(), stamp.downMask(), stamp.upMask()); } }, @@ -1122,6 +1261,13 @@ public class IntegerStamp extends PrimitiveStamp { return new IntegerStamp(resultBits, stamp.lowerBound(), stamp.upperBound(), downMask, upMask); } + + @Override + public Stamp invertStamp(int inputBits, int resultBits, Stamp outStamp) { + IntegerStamp stamp = (IntegerStamp) outStamp; + long mask = CodeUtil.mask(inputBits); + return StampFactory.forIntegerWithMask(inputBits, stamp.lowerBound(), stamp.upperBound(), stamp.downMask() & mask, stamp.upMask() & mask); + } }, new IntegerConvertOp.Narrow() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java index c9df00104c4..d3c64e6d04e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/ObjectStamp.java @@ -80,6 +80,14 @@ public class ObjectStamp extends AbstractObjectStamp { @Override public Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement) { - return provider.readObjectConstant(base, displacement); + try { + return provider.readObjectConstant(base, displacement); + } catch (IllegalArgumentException e) { + /* + * It's possible that the base and displacement aren't valid together so simply return + * null. + */ + return null; + } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java index 4bd3e91bfcd..19e4c69fa25 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/PrimitiveStamp.java @@ -54,7 +54,15 @@ public abstract class PrimitiveStamp extends ArithmeticStamp { @Override public Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement) { - return provider.readPrimitiveConstant(getStackKind(), base, displacement, getBits()); + try { + return provider.readPrimitiveConstant(getStackKind(), base, displacement, getBits()); + } catch (IllegalArgumentException e) { + /* + * It's possible that the base and displacement aren't valid together so simply return + * null. + */ + return null; + } } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java index 0620856ec50..ab7c06363f3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/Stamp.java @@ -125,6 +125,13 @@ public abstract class Stamp { return !hasValues(); } + /** + * Tests whether this stamp represents all values of this kind. + */ + public boolean isUnrestricted() { + return this.equals(this.unrestricted()); + } + /** * If this stamp represents a single value, the methods returns this single value. It returns * null otherwise. @@ -138,6 +145,8 @@ public abstract class Stamp { /** * Read a value of this stamp from memory. + * + * @return the value read or null if the value can't be read for some reason. */ public abstract Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java index 7563067b584..2d94012cf75 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/StampFactory.java @@ -22,6 +22,9 @@ */ package org.graalvm.compiler.core.common.type; +import static jdk.vm.ci.code.CodeUtil.signExtend; + +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.code.CodeUtil; @@ -36,28 +39,6 @@ import jdk.vm.ci.meta.Signature; public class StampFactory { - /* - * The marker stamp for node intrinsics must be its own class, so that it is never equal() to a - * regular ObjectStamp. - */ - static final class NodeIntrinsicStamp extends ObjectStamp { - protected static final Stamp SINGLETON = new NodeIntrinsicStamp(); - - private NodeIntrinsicStamp() { - super(null, false, false, false); - } - - @Override - public int hashCode() { - return System.identityHashCode(this); - } - - @Override - public boolean equals(Object obj) { - return this == obj; - } - } - // JaCoCo Exclude private static final Stamp[] stampCache = new Stamp[JavaKind.values().length]; @@ -82,7 +63,7 @@ public class StampFactory { } else { mask = CodeUtil.mask(bits); } - setCache(kind, new IntegerStamp(bits, kind.getMinValue(), kind.getMaxValue(), 0, mask)); + setCache(kind, IntegerStamp.create(bits, kind.getMinValue(), kind.getMaxValue(), 0, mask)); } private static void setFloatCache(JavaKind kind) { @@ -135,14 +116,6 @@ public class StampFactory { return VoidStamp.getInstance(); } - /** - * A stamp used only in the graph of intrinsics, e.g., snippets. It is then replaced by an - * actual stamp when the intrinsic is used, i.e., when the snippet template is instantiated. - */ - public static Stamp forNodeIntrinsic() { - return NodeIntrinsicStamp.SINGLETON; - } - public static Stamp intValue() { return forKind(JavaKind.Int); } @@ -156,7 +129,7 @@ public class StampFactory { } public static IntegerStamp forInteger(JavaKind kind, long lowerBound, long upperBound, long downMask, long upMask) { - return new IntegerStamp(kind.getBitCount(), lowerBound, upperBound, downMask, upMask); + return IntegerStamp.create(kind.getBitCount(), lowerBound, upperBound, downMask, upMask); } public static IntegerStamp forInteger(JavaKind kind, long lowerBound, long upperBound) { @@ -176,46 +149,35 @@ public class StampFactory { */ public static IntegerStamp forIntegerWithMask(int bits, long newLowerBound, long newUpperBound, IntegerStamp maskStamp) { IntegerStamp limit = StampFactory.forInteger(bits, newLowerBound, newUpperBound); - return new IntegerStamp(bits, newLowerBound, newUpperBound, limit.downMask() | maskStamp.downMask(), limit.upMask() & maskStamp.upMask()); + return IntegerStamp.create(bits, newLowerBound, newUpperBound, limit.downMask() | maskStamp.downMask(), limit.upMask() & maskStamp.upMask()); } public static IntegerStamp forIntegerWithMask(int bits, long newLowerBound, long newUpperBound, long newDownMask, long newUpMask) { IntegerStamp limit = StampFactory.forInteger(bits, newLowerBound, newUpperBound); - return new IntegerStamp(bits, newLowerBound, newUpperBound, limit.downMask() | newDownMask, limit.upMask() & newUpMask); + return IntegerStamp.create(bits, newLowerBound, newUpperBound, limit.downMask() | newDownMask, limit.upMask() & newUpMask); } public static IntegerStamp forInteger(int bits) { - return new IntegerStamp(bits, CodeUtil.minValue(bits), CodeUtil.maxValue(bits), 0, CodeUtil.mask(bits)); + return IntegerStamp.create(bits, CodeUtil.minValue(bits), CodeUtil.maxValue(bits), 0, CodeUtil.mask(bits)); + } + + public static IntegerStamp forUnsignedInteger(int bits, long unsignedLowerBound, long unsignedUpperBound) { + return forUnsignedInteger(bits, unsignedLowerBound, unsignedUpperBound, 0, CodeUtil.mask(bits)); + } + + public static IntegerStamp forUnsignedInteger(int bits, long unsignedLowerBound, long unsignedUpperBound, long downMask, long upMask) { + long lowerBound = signExtend(unsignedLowerBound, bits); + long upperBound = signExtend(unsignedUpperBound, bits); + if (!NumUtil.sameSign(lowerBound, upperBound)) { + lowerBound = CodeUtil.minValue(bits); + upperBound = CodeUtil.maxValue(bits); + } + long mask = CodeUtil.mask(bits); + return IntegerStamp.create(bits, lowerBound, upperBound, downMask & mask, upMask & mask); } public static IntegerStamp forInteger(int bits, long lowerBound, long upperBound) { - long defaultMask = CodeUtil.mask(bits); - if (lowerBound == upperBound) { - return new IntegerStamp(bits, lowerBound, lowerBound, lowerBound & defaultMask, lowerBound & defaultMask); - } - final long downMask; - final long upMask; - if (lowerBound >= 0) { - int upperBoundLeadingZeros = Long.numberOfLeadingZeros(upperBound); - long differentBits = lowerBound ^ upperBound; - int sameBitCount = Long.numberOfLeadingZeros(differentBits << upperBoundLeadingZeros); - - upMask = upperBound | -1L >>> (upperBoundLeadingZeros + sameBitCount); - downMask = upperBound & ~(-1L >>> (upperBoundLeadingZeros + sameBitCount)); - } else { - if (upperBound >= 0) { - upMask = defaultMask; - downMask = 0; - } else { - int lowerBoundLeadingOnes = Long.numberOfLeadingZeros(~lowerBound); - long differentBits = lowerBound ^ upperBound; - int sameBitCount = Long.numberOfLeadingZeros(differentBits << lowerBoundLeadingOnes); - - upMask = lowerBound | -1L >>> (lowerBoundLeadingOnes + sameBitCount) | ~(-1L >>> lowerBoundLeadingOnes); - downMask = lowerBound & ~(-1L >>> (lowerBoundLeadingOnes + sameBitCount)) | ~(-1L >>> lowerBoundLeadingOnes); - } - } - return new IntegerStamp(bits, lowerBound, upperBound, downMask & defaultMask, upMask & defaultMask); + return IntegerStamp.create(bits, lowerBound, upperBound, 0, CodeUtil.mask(bits)); } public static FloatStamp forFloat(JavaKind kind, double lowerBound, double upperBound, boolean nonNaN) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java index 7d3ad60eff4..b867c5ca245 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/type/VoidStamp.java @@ -45,6 +45,11 @@ public final class VoidStamp extends Stamp { return this; } + @Override + public boolean isUnrestricted() { + return true; + } + @Override public JavaKind getStackKind() { return JavaKind.Void; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArrayMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArrayMap.java deleted file mode 100644 index e9a63ffaf86..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArrayMap.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.common.util; - -/** - * The {@code ArrayMap} class implements an efficient one-level map which is implemented as an - * array. Note that because of the one-level array inside, this data structure performs best when - * the range of integer keys is small and densely used. Note that the implementation can handle - * arbitrary intervals, including negative numbers, up to intervals of size 2^31 - 1. - */ -public class ArrayMap { - - private static final int INITIAL_SIZE = 5; // how big the initial array should be - private static final int EXTRA = 2; // how far on the left or right of a new element to grow - - Object[] map; - int low; - - /** - * Constructs a new {@code ArrayMap} with no initial assumptions. - */ - public ArrayMap() { - } - - /** - * Constructs a new {@code ArrayMap} that initially covers the specified interval. Note that - * this map will automatically expand if necessary later. - * - * @param low the low index, inclusive - * @param high the high index, exclusive - */ - public ArrayMap(int low, int high) { - this.low = low; - this.map = new Object[high - low + 1]; - } - - /** - * Puts a new value in the map at the specified index. - * - * @param i the index at which to store the value - * @param value the value to store at the specified index - */ - public void put(int i, T value) { - int index = i - low; - if (map == null) { - // no map yet - map = new Object[INITIAL_SIZE]; - low = index - 2; - map[INITIAL_SIZE / 2] = value; - } else if (index < 0) { - // grow backwards - growBackward(i, value); - } else if (index >= map.length) { - // grow forwards - growForward(i, value); - } else { - // no growth necessary - map[index] = value; - } - } - - /** - * Gets the value at the specified index in the map. - * - * @param i the index - * @return the value at the specified index; {@code null} if there is no value at the specified - * index, or if the index is out of the currently stored range - */ - public T get(int i) { - int index = i - low; - if (map == null || index < 0 || index >= map.length) { - return null; - } - Class type = null; - return Util.uncheckedCast(type, map[index]); - } - - public int length() { - return map.length; - } - - private void growBackward(int i, T value) { - int nlow = i - EXTRA; - Object[] nmap = new Object[low - nlow + map.length]; - System.arraycopy(map, 0, nmap, low - nlow, map.length); - map = nmap; - low = nlow; - map[i - low] = value; - } - - private void growForward(int i, T value) { - int nlen = i - low + 1 + EXTRA; - Object[] nmap = new Object[nlen]; - System.arraycopy(map, 0, nmap, 0, map.length); - map = nmap; - map[i - low] = value; - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/CompilationAlarm.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/CompilationAlarm.java index f97b1712df2..b0dc7fd691d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/CompilationAlarm.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/CompilationAlarm.java @@ -23,8 +23,9 @@ package org.graalvm.compiler.core.common.util; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; /** * Utility class that allows the compiler to monitor compilations that take a very long time. @@ -34,80 +35,74 @@ public final class CompilationAlarm implements AutoCloseable { public static class Options { // @formatter:off @Option(help = "Time limit in seconds before a compilation expires (0 to disable the limit).", type = OptionType.Debug) - public static final OptionValue CompilationExpirationPeriod = new OptionValue<>(300); + public static final OptionKey CompilationExpirationPeriod = new OptionKey<>(300); // @formatter:on } - private CompilationAlarm() { - } - - private static boolean enabled() { - return Options.CompilationExpirationPeriod.getValue() > 0; + private CompilationAlarm(long expiration) { + this.expiration = expiration; } /** - * Thread local storage for compilation start timestamps. Everytime a compiler thread calls - * {@link #trackCompilationPeriod()} it will save the start timestamp of the compilation. + * Thread local storage for the active compilation alarm. */ - private static final ThreadLocal compilationStartedTimeStamps = new ThreadLocal<>(); + private static final ThreadLocal currentAlarm = new ThreadLocal<>(); - private static boolean compilationStarted() { - if (enabled()) { - Long start = compilationStartedTimeStamps.get(); - if (start == null) { - compilationStartedTimeStamps.set(System.currentTimeMillis()); - return true; - } - } - return false; - } + private static final CompilationAlarm NEVER_EXPIRES = new CompilationAlarm(0); - private static void compilationFinished() { - if (enabled()) { - assert compilationStartedTimeStamps.get() != null; - compilationStartedTimeStamps.set(null); - } + /** + * Gets the current compilation alarm. If there is no current alarm, a non-null value is + * returned that will always return {@code false} for {@link #hasExpired()}. + */ + public static CompilationAlarm current() { + CompilationAlarm alarm = currentAlarm.get(); + return alarm == null ? NEVER_EXPIRES : alarm; } /** - * Determines if the current compilation is expired. A compilation expires if it takes longer - * than {@linkplain CompilationAlarm.Options#CompilationExpirationPeriod}. + * Determines if this alarm has expired. A compilation expires if it takes longer than + * {@linkplain CompilationAlarm.Options#CompilationExpirationPeriod}. * * @return {@code true} if the current compilation already takes longer than * {@linkplain CompilationAlarm.Options#CompilationExpirationPeriod}, {@code false} * otherwise */ - public static boolean hasExpired() { - if (enabled()) { - Long start = compilationStartedTimeStamps.get(); - if (start != null) { - long time = System.currentTimeMillis(); - assert time >= start; - return time - start > Options.CompilationExpirationPeriod.getValue() * 1000; - } - } - return false; + public boolean hasExpired() { + return this != NEVER_EXPIRES && System.currentTimeMillis() > expiration; } @Override public void close() { - compilationFinished(); + if (this != NEVER_EXPIRES) { + currentAlarm.set(null); + } } - private static final CompilationAlarm INSTANCE = enabled() ? new CompilationAlarm() : null; + /** + * The time at which this alarm expires. + */ + private final long expiration; /** - * Gets an object that can be used in a try-with-resource statement to set an time limit based - * alarm for a compilation. + * Starts an alarm for setting a time limit on a compilation if there isn't already an active + * alarm and {@link CompilationAlarm.Options#CompilationExpirationPeriod}{@code > 0}. The + * returned value can be used in a try-with-resource statement to disable the alarm once the + * compilation is finished. * - * @return a {@link CompilationAlarm} instance if there is no current alarm for the calling - * thread otherwise {@code null} + * @return a {@link CompilationAlarm} if there was no current alarm for the calling thread + * before this call otherwise {@code null} */ - public static CompilationAlarm trackCompilationPeriod() { - if (compilationStarted()) { - return INSTANCE; + public static CompilationAlarm trackCompilationPeriod(OptionValues options) { + int period = Options.CompilationExpirationPeriod.getValue(options); + if (period > 0) { + CompilationAlarm current = currentAlarm.get(); + if (current == null) { + long expiration = System.currentTimeMillis() + period * 1000; + current = new CompilationAlarm(expiration); + currentAlarm.set(current); + return current; + } } return null; } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java index 736754620cc..09a840b5ca8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java @@ -23,10 +23,10 @@ package org.graalvm.compiler.core.common.util; import java.util.ArrayList; -import java.util.HashMap; -import java.util.IdentityHashMap; import java.util.List; -import java.util.Map; + +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; /** * Creates an array of T objects order by the occurrence frequency of each object. The most @@ -49,24 +49,24 @@ public class FrequencyEncoder { } } - protected final Map> map; + protected final EconomicMap> map; protected boolean containsNull; /** * Creates an encoder that uses object identity. */ public static FrequencyEncoder createIdentityEncoder() { - return new FrequencyEncoder<>(new IdentityHashMap<>()); + return new FrequencyEncoder<>(EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE)); } /** * Creates an encoder that uses {@link Object#equals(Object) object equality}. */ public static FrequencyEncoder createEqualityEncoder() { - return new FrequencyEncoder<>(new HashMap<>()); + return new FrequencyEncoder<>(EconomicMap.create(Equivalence.DEFAULT)); } - protected FrequencyEncoder(Map> map) { + protected FrequencyEncoder(EconomicMap> map) { this.map = map; } @@ -91,7 +91,7 @@ public class FrequencyEncoder { * Returns the index of an object in the array. The object must have been * {@link #addObject(Object) added} before. */ - public int getIndex(Object object) { + public int getIndex(T object) { if (object == null) { assert containsNull; return 0; @@ -114,7 +114,10 @@ public class FrequencyEncoder { */ public T[] encodeAll(T[] allObjects) { assert allObjects.length == getLength(); - List> sortedEntries = new ArrayList<>(map.values()); + List> sortedEntries = new ArrayList<>(allObjects.length); + for (Entry value : map.getValues()) { + sortedEntries.add(value); + } sortedEntries.sort((e1, e2) -> -Integer.compare(e1.frequency, e2.frequency)); int offset = 0; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/IntList.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/IntList.java index 6f58e683bc6..d13d9fecf10 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/IntList.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/IntList.java @@ -31,6 +31,8 @@ import java.util.Arrays; */ public final class IntList { + private static final int[] EMPTY_INT_ARRAY = new int[0]; + private int[] array; private int size; @@ -80,9 +82,13 @@ public final class IntList { */ public static IntList copy(IntList other, int startIndex, int length, int initialCapacity) { assert initialCapacity >= length : "initialCapacity < length"; - int[] array = new int[initialCapacity]; - System.arraycopy(other.array, startIndex, array, 0, length); - return new IntList(array, length); + if (initialCapacity == 0) { + return new IntList(EMPTY_INT_ARRAY, 0); + } else { + int[] array = new int[initialCapacity]; + System.arraycopy(other.array, startIndex, array, 0, length); + return new IntList(array, length); + } } public int size() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java index 86e1bac530a..2c38dfdeba0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -22,12 +22,14 @@ */ package org.graalvm.compiler.core.common.util; -import static org.graalvm.compiler.core.common.util.Util.JAVA_SPECIFICATION_VERSION; +import static org.graalvm.compiler.serviceprovider.JDK9Method.JAVA_SPECIFICATION_VERSION; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import org.graalvm.compiler.debug.GraalError; + /** * Reflection based access to the Module API introduced by JDK 9. This allows the API to be used in * code that must be compiled on a JDK prior to 9. Use of this class must be guarded by a test for @@ -41,11 +43,19 @@ import java.lang.reflect.Modifier; */ public final class ModuleAPI { - private ModuleAPI(Method method) { - this.method = method; + public ModuleAPI(Class declaringClass, String name, Class... parameterTypes) { + try { + this.method = declaringClass.getMethod(name, parameterTypes); + } catch (Exception e) { + throw new GraalError(e); + } } - private final Method method; + public final Method method; + + public Class getReturnType() { + return method.getReturnType(); + } /** * {@code Class.getModule()}. @@ -57,16 +67,6 @@ public final class ModuleAPI { */ public static final ModuleAPI getResourceAsStream; - /** - * {@code java.lang.Module.canRead(Module)}. - */ - public static final ModuleAPI canRead; - - /** - * {@code java.lang.Module.isExported(String)}. - */ - public static final ModuleAPI isExported; - /** * {@code java.lang.Module.isExported(String, Module)}. */ @@ -82,7 +82,7 @@ public final class ModuleAPI { try { return (T) method.invoke(null, args); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new InternalError(e); + throw new GraalError(e); } } @@ -96,35 +96,31 @@ public final class ModuleAPI { try { return (T) method.invoke(receiver, args); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new InternalError(e); + throw new GraalError(e); } } - private void checkAvailability() throws InternalError { + private void checkAvailability() throws GraalError { if (method == null) { - throw new InternalError("Cannot use Module API on JDK " + JAVA_SPECIFICATION_VERSION); + throw new GraalError("Cannot use Module API on JDK " + JAVA_SPECIFICATION_VERSION); } } static { if (JAVA_SPECIFICATION_VERSION >= 9) { - try { - getModule = new ModuleAPI(Class.class.getMethod("getModule")); - Class moduleClass = getModule.method.getReturnType(); - getResourceAsStream = new ModuleAPI(moduleClass.getMethod("getResourceAsStream", String.class)); - canRead = new ModuleAPI(moduleClass.getMethod("canRead", moduleClass)); - isExported = new ModuleAPI(moduleClass.getMethod("isExported", String.class)); - isExportedTo = new ModuleAPI(moduleClass.getMethod("isExported", String.class, moduleClass)); - } catch (NoSuchMethodException | SecurityException e) { - throw new InternalError(e); - } + getModule = new ModuleAPI(Class.class, "getModule"); + Class moduleClass = getModule.getReturnType(); + getResourceAsStream = new ModuleAPI(moduleClass, "getResourceAsStream", String.class); + isExportedTo = new ModuleAPI(moduleClass, "isExported", String.class, moduleClass); } else { - ModuleAPI unavailable = new ModuleAPI(null); + ModuleAPI unavailable = new ModuleAPI(); getModule = unavailable; getResourceAsStream = unavailable; - canRead = unavailable; - isExported = unavailable; isExportedTo = unavailable; } } + + private ModuleAPI() { + method = null; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest2.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ReversedList.java similarity index 52% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest2.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ReversedList.java index e7d01cf5db6..d5fcd1fd12d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest2.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ReversedList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2017, 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 @@ -20,33 +20,39 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.core.test.debug; +package org.graalvm.compiler.core.common.util; -import org.junit.Test; +import java.util.AbstractList; +import java.util.List; +import java.util.RandomAccess; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.phases.Phase; +/** + * A {@code ReversedList} is a view on an other list with the elements in reverse order. + * + * This implementation is made for {@link RandomAccess} lists. + */ +public class ReversedList extends AbstractList implements RandomAccess { + private final List original; -public class MethodMetricsTest2 extends MethodMetricsTest { - - @Override - protected Phase additionalPhase() { - return new MethodMetricPhases.CountingShiftPhase(); + public ReversedList(List original) { + assert original instanceof RandomAccess; + this.original = original; } @Override - DebugConfig getConfig() { - return overrideGraalDebugConfig(System.out, "MethodMetricsTest$TestApplication.*", "CountingShiftPhase"); + public T get(int index) { + return original.get(original.size() - index - 1); } @Override - void assertValues() throws Throwable { - assertValues("Shifts", new long[]{0, 0, 0, 1, 1, 1, 0, 0, 0, 0}); + public int size() { + return original.size(); } - @Test - @Override - public void test() throws Throwable { - super.test(); + /** + * Creates a list that is a view on {@code list} in reverse order. + */ + public static ReversedList reversed(List list) { + return new ReversedList<>(list); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java index 4e29d619daa..ef3669b0673 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/Util.java @@ -22,9 +22,9 @@ */ package org.graalvm.compiler.core.common.util; -import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; - -import java.util.Collection; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Executable; +import java.lang.reflect.Field; import java.util.List; import org.graalvm.compiler.debug.TTY; @@ -39,25 +39,6 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; */ public class Util { - private static int getJavaSpecificationVersion() { - String value = System.getProperty("java.specification.version"); - if (value.startsWith("1.")) { - value = value.substring(2); - } - return Integer.parseInt(value); - } - - /** - * The integer value corresponding to the value of the {@code java.specification.version} system - * property after any leading {@code "1."} has been stripped. - */ - public static final int JAVA_SPECIFICATION_VERSION = getJavaSpecificationVersion(); - - /** - * Determines if the Java runtime is version 8 or earlier. - */ - public static final boolean Java8OrEarlier = JAVA_SPECIFICATION_VERSION <= 8; - /** * Statically cast an object to an arbitrary Object type. Dynamically checked. */ @@ -74,29 +55,6 @@ public class Util { return (T) object; } - public interface Stringify { - String apply(Object o); - } - - public static String join(Collection c, String sep) { - return join(c, sep, "", "", null); - } - - public static String join(Collection c, String sep, String prefix, String suffix, Stringify stringify) { - StringBuilder buf = new StringBuilder(prefix); - boolean first = true; - for (Object e : c) { - if (!first) { - buf.append(sep); - } else { - first = false; - } - buf.append(stringify != null ? stringify.apply(e) : String.valueOf(e)); - } - buf.append(suffix); - return buf.toString(); - } - /** * Sets the element at a given position of a list and ensures that this position exists. If the * list is current shorter than the position, intermediate positions are filled with a given @@ -191,25 +149,39 @@ public class Util { * Print a HotSpot-style inlining message to the console. */ public static void printInlining(final ResolvedJavaMethod method, final int bci, final int inliningDepth, final boolean success, final String msg, final Object... args) { - if (HotSpotPrintInlining.getValue()) { - StringBuilder sb = new StringBuilder(); - // 1234567 - sb.append(" "); // print timestamp - // 1234 - sb.append(" "); // print compilation number - // % s ! b n - sb.append(String.format("%c%c%c%c%c ", ' ', method.isSynchronized() ? 's' : ' ', ' ', ' ', method.isNative() ? 'n' : ' ')); - sb.append(" "); // more indent - sb.append(" "); // initial inlining indent - for (int i = 0; i < inliningDepth; i++) { - sb.append(" "); - } - sb.append(String.format("@ %d %s %s%s", bci, methodName(method), success ? "" : "not inlining ", String.format(msg, args))); - TTY.println(sb.toString()); + StringBuilder sb = new StringBuilder(); + // 1234567 + sb.append(" "); // print timestamp + // 1234 + sb.append(" "); // print compilation number + // % s ! b n + sb.append(String.format("%c%c%c%c%c ", ' ', method.isSynchronized() ? 's' : ' ', ' ', ' ', method.isNative() ? 'n' : ' ')); + sb.append(" "); // more indent + sb.append(" "); // initial inlining indent + for (int i = 0; i < inliningDepth; i++) { + sb.append(" "); } + sb.append(String.format("@ %d %s %s%s", bci, methodName(method), success ? "" : "not inlining ", String.format(msg, args))); + TTY.println(sb.toString()); } private static String methodName(ResolvedJavaMethod method) { return method.format("%H.%n(%p):%r") + " (" + method.getCodeSize() + " bytes)"; } + + /** + * Calls {@link AccessibleObject#setAccessible(boolean)} on {@code field} with the value + * {@code flag}. + */ + public static void setAccessible(Field field, boolean flag) { + field.setAccessible(flag); + } + + /** + * Calls {@link AccessibleObject#setAccessible(boolean)} on {@code executable} with the value + * {@code flag}. + */ + public static void setAccessible(Executable executable, boolean flag) { + executable.setAccessible(flag); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java index 5129a503b7e..7351a71116d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java @@ -27,12 +27,8 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -74,6 +70,9 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Position; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.serviceprovider.ServiceProvider; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.EconomicSet; /** * Processes classes annotated with {@link MatchRule}. A {@link MatchStatementSet} service is @@ -206,13 +205,13 @@ public class MatchProcessor extends AbstractProcessor { name = next(); } originatingElements.addAll(type.originatingElements); - requiredPackages.add(type.nodePackage); } else if (Character.isLowerCase(peek("name").charAt(0))) { name = next(); type = valueType; } else { throw new RuleParseError("Unexpected token \"%s\" when looking for name or node type", peek(null)); } + requiredPackages.add(type.nodePackage); if (name != null) { if (!capturedNames.contains(name)) { capturedNames.add(name); @@ -234,7 +233,7 @@ public class MatchProcessor extends AbstractProcessor { /** * Recursively accumulate any required Position declarations. */ - void generatePositionDeclarations(Set declarations) { + void generatePositionDeclarations(EconomicSet declarations) { matchDescriptor.generatePositionDeclarations(declarations); } @@ -366,7 +365,7 @@ public class MatchProcessor extends AbstractProcessor { /** * The types which are know for purpose of parsing MatchRule expressions. */ - Map knownTypes = new HashMap<>(); + EconomicMap knownTypes = EconomicMap.create(Equivalence.DEFAULT); private TypeDescriptor valueType; @@ -407,7 +406,7 @@ public class MatchProcessor extends AbstractProcessor { } } - public void generatePositionDeclarations(Set declarations) { + public void generatePositionDeclarations(EconomicSet declarations) { if (inputs.length == 0) { return; } @@ -532,7 +531,7 @@ public class MatchProcessor extends AbstractProcessor { out.println(); // Generate declarations for the wrapper class to invoke the code generation methods. - for (MethodInvokerItem invoker : info.invokers.values()) { + for (MethodInvokerItem invoker : info.invokers.getValues()) { StringBuilder args = new StringBuilder(); StringBuilder types = new StringBuilder(); int count = invoker.fields.size(); @@ -663,14 +662,14 @@ public class MatchProcessor extends AbstractProcessor { final TypeElement topDeclaringType; final List matchRules = new ArrayList<>(); - private final Set originatingElements = new HashSet<>(); - public Set positionDeclarations = new LinkedHashSet<>(); + private final EconomicSet originatingElements = EconomicSet.create(Equivalence.DEFAULT); + public EconomicSet positionDeclarations = EconomicSet.create(Equivalence.DEFAULT); /** * The mapping between elements with MatchRules and the wrapper class used invoke the code * generation after the match. */ - Map invokers = new LinkedHashMap<>(); + EconomicMap invokers = EconomicMap.create(Equivalence.DEFAULT); /** * The set of packages which must be imported to refer the classes mention in matchRules. @@ -728,7 +727,7 @@ public class MatchProcessor extends AbstractProcessor { TypeMirror valueTypeMirror = processingEnv.getElementUtils().getTypeElement(ValueNode.class.getName()).asType(); valueType = new TypeDescriptor(valueTypeMirror, "Value", ValueNode.class.getSimpleName(), ValueNode.class.getPackage().getName(), new String[0], false, false); - Map map = new LinkedHashMap<>(); + EconomicMap map = EconomicMap.create(Equivalence.DEFAULT); for (Element element : roundEnv.getElementsAnnotatedWith(MatchRule.class)) { currentElement = element; @@ -740,7 +739,7 @@ public class MatchProcessor extends AbstractProcessor { } currentElement = null; - for (MatchRuleDescriptor info : map.values()) { + for (MatchRuleDescriptor info : map.getValues()) { createFiles(info); } @@ -834,7 +833,7 @@ public class MatchProcessor extends AbstractProcessor { declareType(nodeClassMirror, shortName, nodeClass, nodePackage, matchable.inputs(), matchable.commutative(), matchable.shareable(), element); } - private void processMatchRule(Map map, Element element, AnnotationMirror mirror) { + private void processMatchRule(EconomicMap map, Element element, AnnotationMirror mirror) { if (!processedMatchRule.contains(element)) { try { processedMatchRule.add(element); @@ -961,7 +960,7 @@ public class MatchProcessor extends AbstractProcessor { Element enclosing = method.getEnclosingElement(); String declaringClass = ""; String separator = ""; - Set originatingElementsList = info.originatingElements; + EconomicSet originatingElementsList = info.originatingElements; originatingElementsList.add(method); while (enclosing != null) { if (enclosing.getKind() == ElementKind.CLASS || enclosing.getKind() == ElementKind.INTERFACE) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java index e0f57456f04..b1171dba201 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc.test/src/org/graalvm/compiler/core/sparc/test/SPARCAllocatorTest.java @@ -22,23 +22,24 @@ */ package org.graalvm.compiler.core.sparc.test; -import static org.graalvm.compiler.core.common.GraalOptions.TraceRA; import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure; +import static org.graalvm.compiler.core.common.GraalOptions.TraceRA; import static org.junit.Assume.assumeTrue; -import jdk.vm.ci.sparc.SPARC; import org.junit.Before; import org.junit.Test; import org.graalvm.compiler.core.test.backend.AllocatorTest; +import jdk.vm.ci.sparc.SPARC; + public class SPARCAllocatorTest extends AllocatorTest { @Before public void checkSPARC() { assumeTrue("skipping SPARC specific test", getTarget().arch instanceof SPARC); - assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue() == null); - assumeTrue("TraceRA is set -> skip", !TraceRA.getValue()); + assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue(getInitialOptions()) == null); + assumeTrue("TraceRA is set -> skip", !TraceRA.getValue(getInitialOptions())); } @Test @@ -47,7 +48,7 @@ public class SPARCAllocatorTest extends AllocatorTest { } public static long test1snippet(long x) { - return x + 5; + return x + 41; } @Test @@ -56,7 +57,7 @@ public class SPARCAllocatorTest extends AllocatorTest { } public static long test2snippet(long x) { - return x * 5; + return x * 41; } @Test @@ -65,7 +66,7 @@ public class SPARCAllocatorTest extends AllocatorTest { } public static long test3snippet(long x) { - return x / 3 + x % 3; + return x / 41 + x % 41; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java index 5edf7793eb5..9cee4a471e6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2017, 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 @@ -113,12 +113,8 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { @Override public Variable emitBitCount(Value operand) { Variable result = getLIRGen().newVariable(LIRKind.combine(operand).changeType(SPARCKind.WORD)); - Value usedOperand = operand; - if (operand.getPlatformKind() == SPARCKind.WORD) { // Zero extend - usedOperand = getLIRGen().newVariable(operand.getValueKind()); - getLIRGen().append(new SPARCOP3Op(Op3s.Srl, operand, SPARC.g0.asValue(), usedOperand)); - } - getLIRGen().append(new SPARCOP3Op(Op3s.Popc, SPARC.g0.asValue(), usedOperand, result)); + AllocatableValue usedOperand = getLIRGen().asAllocatable(emitZeroExtend(operand)); + getLIRGen().append(new SPARCOP3Op(Op3s.Popc, g0.asValue(), usedOperand, result)); return result; } @@ -141,9 +137,9 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { } @Override - public Value emitMathAbs(Value input) { - Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - SPARCKind kind = (SPARCKind) input.getPlatformKind(); + public Value emitMathAbs(Value inputValue) { + Variable result = getLIRGen().newVariable(LIRKind.combine(inputValue)); + SPARCKind kind = (SPARCKind) inputValue.getPlatformKind(); Opfs opf; switch (kind) { case SINGLE: @@ -155,14 +151,14 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { default: throw GraalError.shouldNotReachHere("Input kind: " + kind); } - getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result)); + getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), getLIRGen().asAllocatable(inputValue), result)); return result; } @Override - public Value emitMathSqrt(Value input) { - Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - SPARCKind kind = (SPARCKind) input.getPlatformKind(); + public Value emitMathSqrt(Value inputValue) { + Variable result = getLIRGen().newVariable(LIRKind.combine(inputValue)); + SPARCKind kind = (SPARCKind) inputValue.getPlatformKind(); Opfs opf; switch (kind) { case SINGLE: @@ -174,7 +170,7 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { default: throw GraalError.shouldNotReachHere("Input kind: " + kind); } - getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result)); + getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), getLIRGen().asAllocatable(inputValue), result)); return result; } @@ -193,15 +189,15 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { return emitUnary(Xnor, input); } - private Variable emitUnary(Opfs opf, Value input) { - Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), input, result)); + private Variable emitUnary(Opfs opf, Value inputValue) { + Variable result = getLIRGen().newVariable(LIRKind.combine(inputValue)); + getLIRGen().append(new SPARCOPFOp(opf, g0.asValue(), getLIRGen().asAllocatable(inputValue), result)); return result; } private Variable emitUnary(Op3s op3, Value input) { Variable result = getLIRGen().newVariable(LIRKind.combine(input)); - getLIRGen().append(SPARCOP3Op.newUnary(op3, input, result)); + getLIRGen().append(SPARCOP3Op.newUnary(op3, getLIRGen().loadSimm13(input), result)); return result; } @@ -211,11 +207,7 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { private Variable emitBinary(ValueKind resultKind, Opfs opf, Value a, Value b, LIRFrameState state) { Variable result = getLIRGen().newVariable(resultKind); - if (opf.isCommutative() && isJavaConstant(a) && getLIRGen().getMoveFactory().canInlineConstant(asJavaConstant(a))) { - getLIRGen().append(new SPARCOPFOp(opf, b, a, result, state)); - } else { - getLIRGen().append(new SPARCOPFOp(opf, a, b, result, state)); - } + getLIRGen().append(new SPARCOPFOp(opf, getLIRGen().asAllocatable(a), getLIRGen().asAllocatable(b), result, state)); return result; } @@ -230,9 +222,9 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { private Variable emitBinary(ValueKind resultKind, Op3s op3, Value a, Value b, LIRFrameState state) { Variable result = getLIRGen().newVariable(resultKind); if (op3.isCommutative() && isJavaConstant(a) && getLIRGen().getMoveFactory().canInlineConstant(asJavaConstant(a))) { - getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(b), a, result, state)); + getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(b), getLIRGen().loadSimm13(a), result, state)); } else { - getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(a), b, result, state)); + getLIRGen().append(new SPARCOP3Op(op3, getLIRGen().load(a), getLIRGen().loadSimm13(b), result, state)); } return result; } @@ -278,7 +270,7 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { } return result; } else { - return emitBinary(resultKind, setFlags ? Op3s.Mulscc : Op3s.Mulx, a, b); + return emitBinary(resultKind, Op3s.Mulx, a, b); } } else { boolean isDouble = a.getPlatformKind().equals(DOUBLE); @@ -306,9 +298,7 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { public Value emitUMulHigh(Value a, Value b) { switch (((SPARCKind) a.getPlatformKind())) { case WORD: - Value aExtended = emitBinary(LIRKind.combine(a), Srl, a, 0); - Value bExtended = emitBinary(LIRKind.combine(b), Srl, b, 0); - Value result = emitBinary(LIRKind.combine(a, b), Mulx, aExtended, bExtended); + Value result = emitBinary(LIRKind.combine(a, b), Mulx, emitZeroExtend(a), emitZeroExtend(b)); return emitBinary(LIRKind.combine(a, b), Srax, result, WORD.getSizeInBits()); case XWORD: return emitBinary(LIRKind.combine(a, b), UMulxhi, a, b); @@ -327,17 +317,13 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { @Override public Value emitDiv(Value a, Value b, LIRFrameState state) { LIRKind resultKind = LIRKind.combine(a, b); - PlatformKind aKind = a.getPlatformKind(); - PlatformKind bKind = b.getPlatformKind(); if (isJavaConstant(b) && asJavaConstant(b).isDefaultForKind()) { // Div by zero Value zero = SPARC.g0.asValue(LIRKind.value(SPARCKind.WORD)); return emitBinary(resultKind, Op3s.Sdivx, zero, zero, state); - } else if (isNumericInteger(aKind)) { - Value fixedA = emitSignExtend(a, aKind.getSizeInBytes() * 8, 64); - Value fixedB = emitSignExtend(b, bKind.getSizeInBytes() * 8, 64); - return emitBinary(resultKind, Op3s.Sdivx, fixedA, fixedB, state); + } else if (isNumericInteger(a.getPlatformKind())) { + return emitBinary(resultKind, Op3s.Sdivx, emitSignExtend(a), emitSignExtend(b), state); } else { - boolean isDouble = a.getPlatformKind().equals(DOUBLE); + boolean isDouble = a.getPlatformKind() == DOUBLE; return emitBinary(resultKind, isDouble ? Opfs.Fdivd : Opfs.Fdivs, a, b, state); } } @@ -345,24 +331,21 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { @Override public Value emitRem(Value a, Value b, LIRFrameState state) { Variable result = getLIRGen().newVariable(LIRKind.combine(a, b)); - Value aLoaded; Variable q1; // Intermediate values Variable q2; - SPARCKind aKind = (SPARCKind) a.getPlatformKind(); - switch (aKind) { + switch ((SPARCKind) a.getPlatformKind()) { case WORD: // Sign extend a and b - Variable as = emitBinary(result.getValueKind(), Sra, a, g0.asValue(LIRKind.value(WORD))); - Variable bs = emitBinary(result.getValueKind(), Sra, b, g0.asValue(LIRKind.value(WORD))); + Value as = emitSignExtend(a); + Value bs = emitSignExtend(b); q1 = emitBinary(as.getValueKind(), Sdivx, as, bs, state); - q2 = emitBinary(q1.getValueKind(), Mulx, q1, bs); + q2 = emitBinary(as.getValueKind(), Mulx, q1, bs); result = emitSub(as, q2, false); break; case XWORD: - aLoaded = getLIRGen().load(a); // Reuse the loaded value - q1 = emitBinary(result.getValueKind(), Sdivx, aLoaded, b, state); + q1 = emitBinary(result.getValueKind(), Sdivx, a, b, state); q2 = emitBinary(result.getValueKind(), Mulx, q1, b); - result = emitSub(aLoaded, q2, false); + result = emitSub(a, q2, false); break; case SINGLE: ForeignCallLinkage fremCall = getLIRGen().getForeignCalls().lookupForeignCall(ARITHMETIC_FREM); @@ -394,26 +377,14 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { default: throw GraalError.shouldNotReachHere(); } - getLIRGen().append(new RemOp(opcode, result, getLIRGen().load(a), getLIRGen().load(b), scratch1, scratch2, state)); + getLIRGen().append(new RemOp(opcode, result, getLIRGen().asAllocatable(a), getLIRGen().asAllocatable(b), scratch1, scratch2, state)); return result; } @Override public Value emitUDiv(Value a, Value b, LIRFrameState state) { - Value actualA = a; - Value actualB = b; - switch (((SPARCKind) a.getPlatformKind())) { - case WORD: - actualA = emitZeroExtend(actualA, 32, 64); - actualB = emitZeroExtend(actualB, 32, 64); - break; - case XWORD: - break; - default: - throw GraalError.shouldNotReachHere(); - } - return emitBinary(LIRKind.combine(actualA, actualB), Udivx, actualA, actualB, state); + return emitBinary(LIRKind.combine(a, b), Udivx, emitZeroExtend(a), emitZeroExtend(b), state); } @Override @@ -495,78 +466,78 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { } @Override - public Value emitFloatConvert(FloatConvert op, Value inputVal) { - AllocatableValue input = getLIRGen().asAllocatable(inputVal); - Value result; + public Value emitFloatConvert(FloatConvert op, Value inputValue) { + AllocatableValue inputAllocatable = getLIRGen().asAllocatable(inputValue); + AllocatableValue result; switch (op) { case D2F: - result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(SINGLE)); - getLIRGen().append(new SPARCOPFOp(Fdtos, inputVal, result)); + result = getLIRGen().newVariable(LIRKind.combine(inputValue).changeType(SINGLE)); + getLIRGen().append(new SPARCOPFOp(Fdtos, inputAllocatable, result)); break; case F2D: - result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(DOUBLE)); - getLIRGen().append(new SPARCOPFOp(Fstod, inputVal, result)); + result = getLIRGen().newVariable(LIRKind.combine(inputValue).changeType(DOUBLE)); + getLIRGen().append(new SPARCOPFOp(Fstod, inputAllocatable, result)); break; case I2F: { - AllocatableValue intEncodedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); + AllocatableValue intEncodedFloatReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); result = getLIRGen().newVariable(intEncodedFloatReg.getValueKind()); - moveBetweenFpGp(intEncodedFloatReg, input); + moveBetweenFpGp(intEncodedFloatReg, inputAllocatable); getLIRGen().append(new SPARCOPFOp(Fitos, intEncodedFloatReg, result)); break; } case I2D: { // Unfortunately we must do int -> float -> double because fitod has float // and double encoding in one instruction - AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); - result = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - moveBetweenFpGp(convertedFloatReg, input); + AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); + result = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + moveBetweenFpGp(convertedFloatReg, inputAllocatable); getLIRGen().append(new SPARCOPFOp(Fitod, convertedFloatReg, result)); break; } case L2D: { - AllocatableValue longEncodedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - moveBetweenFpGp(longEncodedDoubleReg, input); + AllocatableValue longEncodedDoubleReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + moveBetweenFpGp(longEncodedDoubleReg, inputAllocatable); AllocatableValue convertedDoubleReg = getLIRGen().newVariable(longEncodedDoubleReg.getValueKind()); getLIRGen().append(new SPARCOPFOp(Fxtod, longEncodedDoubleReg, convertedDoubleReg)); result = convertedDoubleReg; break; } case D2I: { - AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); - getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2I, input, convertedFloatReg)); + AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); + getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2I, inputAllocatable, convertedFloatReg)); AllocatableValue convertedIntReg = getLIRGen().newVariable(LIRKind.combine(convertedFloatReg).changeType(WORD)); moveBetweenFpGp(convertedIntReg, convertedFloatReg); result = convertedIntReg; break; } case F2L: { - AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2L, input, convertedDoubleReg)); + AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2L, inputAllocatable, convertedDoubleReg)); AllocatableValue convertedLongReg = getLIRGen().newVariable(LIRKind.combine(convertedDoubleReg).changeType(XWORD)); moveBetweenFpGp(convertedLongReg, convertedDoubleReg); result = convertedLongReg; break; } case F2I: { - AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); - getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2I, input, convertedFloatReg)); + AllocatableValue convertedFloatReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); + getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.F2I, inputAllocatable, convertedFloatReg)); AllocatableValue convertedIntReg = getLIRGen().newVariable(LIRKind.combine(convertedFloatReg).changeType(WORD)); moveBetweenFpGp(convertedIntReg, convertedFloatReg); result = convertedIntReg; break; } case D2L: { - AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2L, input, convertedDoubleReg)); + AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + getLIRGen().append(new SPARCArithmetic.FloatConvertOp(FloatConvertOp.FloatConvert.D2L, inputAllocatable, convertedDoubleReg)); AllocatableValue convertedLongReg = getLIRGen().newVariable(LIRKind.combine(convertedDoubleReg).changeType(XWORD)); moveBetweenFpGp(convertedLongReg, convertedDoubleReg); result = convertedLongReg; break; } case L2F: { - AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(input).changeType(DOUBLE)); - result = getLIRGen().newVariable(LIRKind.combine(input).changeType(SINGLE)); - moveBetweenFpGp(convertedDoubleReg, input); + AllocatableValue convertedDoubleReg = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(DOUBLE)); + result = getLIRGen().newVariable(LIRKind.combine(inputAllocatable).changeType(SINGLE)); + moveBetweenFpGp(convertedDoubleReg, inputAllocatable); getLIRGen().append(new SPARCOPFOp(Opfs.Fxtos, convertedDoubleReg, result)); break; } @@ -604,15 +575,19 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { } } + private Value emitSignExtend(Value inputValue) { + int inputBits = inputValue.getPlatformKind().getSizeInBytes() * 8; + return emitNarrow(emitSignExtend(inputValue, inputBits, XWORD.getSizeInBits()), inputBits); + } + @Override public Value emitSignExtend(Value inputVal, int fromBits, int toBits) { assert fromBits <= toBits && toBits <= XWORD.getSizeInBits(); LIRKind shiftKind = LIRKind.value(WORD); LIRKind resultKind = LIRKind.combine(inputVal).changeType(toBits > 32 ? XWORD : WORD); - Value result; int shiftCount = XWORD.getSizeInBits() - fromBits; if (fromBits == toBits) { - result = inputVal; + return inputVal; } else if (isJavaConstant(inputVal)) { JavaConstant javaConstant = asJavaConstant(inputVal); long constant; @@ -622,30 +597,38 @@ public class SPARCArithmeticLIRGenerator extends ArithmeticLIRGenerator { constant = javaConstant.asLong(); } return new ConstantValue(resultKind, JavaConstant.forLong((constant << shiftCount) >> shiftCount)); - } else if (fromBits == WORD.getSizeInBits() && toBits == XWORD.getSizeInBits()) { - result = getLIRGen().newVariable(resultKind); - getLIRGen().append(new SPARCOP3Op(Sra, inputVal, SPARC.g0.asValue(LIRKind.value(WORD)), result)); } else { - Variable tmp = getLIRGen().newVariable(resultKind.changeType(XWORD)); - result = getLIRGen().newVariable(resultKind); - getLIRGen().append(new SPARCOP3Op(Sllx, inputVal, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), tmp)); - getLIRGen().append(new SPARCOP3Op(Srax, tmp, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), result)); + AllocatableValue inputAllocatable = getLIRGen().asAllocatable(inputVal); + Variable result = getLIRGen().newVariable(resultKind); + if (fromBits == WORD.getSizeInBits() && toBits == XWORD.getSizeInBits()) { + getLIRGen().append(new SPARCOP3Op(Sra, inputAllocatable, g0.asValue(LIRKind.value(WORD)), result)); + } else { + Variable tmp = getLIRGen().newVariable(resultKind.changeType(XWORD)); + getLIRGen().append(new SPARCOP3Op(Sllx, inputAllocatable, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), tmp)); + getLIRGen().append(new SPARCOP3Op(Srax, tmp, new ConstantValue(shiftKind, JavaConstant.forInt(shiftCount)), result)); + } + return result; } - return result; + } + + private Value emitZeroExtend(Value inputValue) { + int inputBits = inputValue.getPlatformKind().getSizeInBytes() * 8; + return emitNarrow(emitZeroExtend(inputValue, inputBits, XWORD.getSizeInBits()), inputBits); } @Override - public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) { + public Value emitZeroExtend(Value inputValue, int fromBits, int toBits) { assert fromBits <= toBits && toBits <= 64; if (fromBits == toBits) { - return inputVal; + return inputValue; } - Variable result = getLIRGen().newVariable(LIRKind.combine(inputVal).changeType(toBits > WORD.getSizeInBits() ? XWORD : WORD)); + Variable result = getLIRGen().newVariable(LIRKind.combine(inputValue).changeType(toBits > WORD.getSizeInBits() ? XWORD : WORD)); + AllocatableValue inputAllocatable = getLIRGen().asAllocatable(inputValue); if (fromBits == 32) { - getLIRGen().append(new SPARCOP3Op(Srl, inputVal, g0.asValue(), result)); + getLIRGen().append(new SPARCOP3Op(Srl, inputAllocatable, g0.asValue(), result)); } else { Value mask = getLIRGen().emitConstant(LIRKind.value(XWORD), forLong(mask(fromBits))); - getLIRGen().append(new SPARCOP3Op(And, inputVal, mask, result)); + getLIRGen().append(new SPARCOP3Op(And, inputAllocatable, mask, result)); } return result; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java index 0716b556974..abdef18c51e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCImmediateAddressNode.java @@ -67,4 +67,19 @@ public class SPARCImmediateAddressNode extends AddressNode implements LIRLowerab gen.setResult(this, new SPARCImmediateAddressValue(kind, baseValue, displacement)); } + + @Override + public ValueNode getBase() { + return base; + } + + @Override + public long getMaxConstantDisplacement() { + return displacement; + } + + @Override + public ValueNode getIndex() { + return null; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java index 06c5725369e..3fee3e82ea1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCIndexedAddressNode.java @@ -65,6 +65,7 @@ public class SPARCIndexedAddressNode extends AddressNode implements LIRLowerable gen.setResult(this, new SPARCIndexedAddressValue(kind, baseValue, indexValue)); } + @Override public ValueNode getBase() { return base; } @@ -74,6 +75,7 @@ public class SPARCIndexedAddressNode extends AddressNode implements LIRLowerable this.base = base; } + @Override public ValueNode getIndex() { return index; } @@ -82,4 +84,9 @@ public class SPARCIndexedAddressNode extends AddressNode implements LIRLowerable updateUsages(this.index, index); this.index = index; } + + @Override + public long getMaxConstantDisplacement() { + return Long.MAX_VALUE; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java index 0023a12738c..95f3e5c58c5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2017, 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 @@ -194,16 +194,16 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { @Override public void emitCompareBranch(PlatformKind cmpKind, Value x, Value y, Condition cond, boolean unorderedIsTrue, LabelRef trueDestination, LabelRef falseDestination, double trueDestinationProbability) { - Value left; + AllocatableValue left; Value right; Condition actualCondition; if (isJavaConstant(x)) { left = load(y); - right = loadNonConst(x); + right = loadSimm13(x); actualCondition = cond.mirror(); } else { left = load(x); - right = loadNonConst(y); + right = loadSimm13(y); actualCondition = cond; } SPARCKind actualCmpKind = (SPARCKind) cmpKind; @@ -234,9 +234,9 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { private void emitIntegerTest(Value a, Value b) { assert ((SPARCKind) a.getPlatformKind()).isInteger(); if (LIRValueUtil.isVariable(b)) { - append(SPARCOP3Op.newBinaryVoid(Op3s.Andcc, load(b), loadNonConst(a))); + append(SPARCOP3Op.newBinaryVoid(Op3s.Andcc, load(b), loadSimm13(a))); } else { - append(SPARCOP3Op.newBinaryVoid(Op3s.Andcc, load(a), loadNonConst(b))); + append(SPARCOP3Op.newBinaryVoid(Op3s.Andcc, load(a), loadSimm13(b))); } } @@ -250,6 +250,23 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { return load(value); } + public Value loadSimm13(Value value) { + if (isJavaConstant(value)) { + JavaConstant c = asJavaConstant(value); + if (c.isNull() || SPARCAssembler.isSimm13(c)) { + return value; + } + } + return load(value); + } + + @Override + public Value loadNonConst(Value value) { + // SPARC does not support a proper way of loadNonConst. Please use the appropriate + // loadSimm11 or loadSimm13 variants. + throw GraalError.shouldNotReachHere("This operation is not available for SPARC."); + } + @Override public Variable emitConditionalMove(PlatformKind cmpKind, Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) { // Emit compare @@ -304,24 +321,24 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { private boolean emitIntegerCompare(SPARCKind cmpKind, Value a, Value b) { boolean mirrored; assert cmpKind.isInteger(); - Value left; + AllocatableValue left; Value right; if (LIRValueUtil.isVariable(b)) { left = load(b); - right = loadNonConst(a); + right = loadSimm13(a); mirrored = true; } else { left = load(a); - right = loadNonConst(b); + right = loadSimm13(b); mirrored = false; } int compareBytes = cmpKind.getSizeInBytes(); // SPARC compares 32 or 64 bits if (compareBytes < left.getPlatformKind().getSizeInBytes()) { - left = arithmeticLIRGen.emitSignExtend(left, compareBytes * 8, XWORD.getSizeInBytes() * 8); + left = asAllocatable(arithmeticLIRGen.emitSignExtend(left, cmpKind.getSizeInBits(), XWORD.getSizeInBits())); } if (compareBytes < right.getPlatformKind().getSizeInBytes()) { - right = arithmeticLIRGen.emitSignExtend(right, compareBytes * 8, XWORD.getSizeInBytes() * 8); + right = arithmeticLIRGen.emitSignExtend(right, cmpKind.getSizeInBits(), XWORD.getSizeInBits()); } append(SPARCOP3Op.newBinaryVoid(Subcc, left, right)); return mirrored; @@ -365,10 +382,10 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { @Override public void emitStrategySwitch(SwitchStrategy strategy, Variable key, LabelRef[] keyTargets, LabelRef defaultTarget) { - AllocatableValue scratchValue = newVariable(key.getValueKind()); + Variable scratchValue = newVariable(key.getValueKind()); AllocatableValue base = AllocatableValue.ILLEGAL; for (Constant c : strategy.getKeyConstants()) { - if (!(c instanceof JavaConstant) || !getMoveFactory().canInlineConstant((JavaConstant) c)) { + if (!getMoveFactory().canInlineConstant(c)) { base = constantTableBaseProvider.getConstantTableBase(); break; } @@ -376,7 +393,7 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { append(createStrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue)); } - protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue scratchValue) { + protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, Variable scratchValue) { return new StrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue); } @@ -396,7 +413,7 @@ public abstract class SPARCLIRGenerator extends LIRGenerator { @Override public Variable emitByteSwap(Value input) { Variable result = newVariable(LIRKind.combine(input)); - append(new SPARCByteSwapOp(this, result, input)); + append(new SPARCByteSwapOp(this, result, asAllocatable(input))); return result; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRKindTool.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRKindTool.java index c075a51e3df..d24c4215f48 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRKindTool.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCLIRKindTool.java @@ -65,4 +65,14 @@ public class SPARCLIRKindTool implements LIRKindTool { public LIRKind getWordKind() { return LIRKind.value(SPARCKind.XWORD); } + + @Override + public LIRKind getNarrowOopKind() { + return LIRKind.reference(SPARCKind.WORD); + } + + @Override + public LIRKind getNarrowPointerKind() { + return LIRKind.value(SPARCKind.WORD); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java index 17395808f8e..0d545ba9367 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java @@ -91,21 +91,33 @@ public class SPARCMoveFactory implements MoveFactory { } @Override - public boolean canInlineConstant(JavaConstant c) { - switch (c.getJavaKind()) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - return SPARCAssembler.isSimm13(c.asInt()); - case Long: - return SPARCAssembler.isSimm13(c.asLong()); - case Object: - return c.isNull(); - default: - return false; + public LIRInstruction createStackLoad(AllocatableValue result, Constant input) { + if (input instanceof DataPointerConstant) { + throw GraalError.shouldNotReachHere("unsupported constant for stack load: " + input); } + return createLoad(result, input); + } + + @Override + public boolean canInlineConstant(Constant con) { + if (con instanceof JavaConstant) { + JavaConstant c = (JavaConstant) con; + switch (c.getJavaKind()) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + return SPARCAssembler.isSimm13(c.asInt()); + case Long: + return SPARCAssembler.isSimm13(c.asLong()); + case Object: + return c.isNull(); + default: + return false; + } + } + return false; } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java index a8bbdbe7f97..53c137fe193 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCNodeMatchRules.java @@ -29,17 +29,27 @@ import static jdk.vm.ci.sparc.SPARCKind.WORD; import static jdk.vm.ci.sparc.SPARCKind.XWORD; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.gen.NodeMatchRules; import org.graalvm.compiler.core.match.ComplexMatchResult; import org.graalvm.compiler.core.match.MatchRule; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LabelRef; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; +import org.graalvm.compiler.lir.sparc.SPARCAddressValue; import org.graalvm.compiler.nodes.DeoptimizingNode; +import org.graalvm.compiler.nodes.IfNode; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.CompareNode; import org.graalvm.compiler.nodes.calc.SignExtendNode; import org.graalvm.compiler.nodes.calc.ZeroExtendNode; +import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.Access; +import org.graalvm.compiler.nodes.memory.LIRLowerableAccess; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.Value; import jdk.vm.ci.sparc.SPARCKind; /** @@ -58,6 +68,10 @@ public class SPARCNodeMatchRules extends NodeMatchRules { return null; } + protected LIRKind getLirKind(LIRLowerableAccess access) { + return gen.getLIRKind(access.getAccessStamp()); + } + private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits) { assert fromBits <= toBits && toBits <= 64; SPARCKind toKind = null; @@ -127,6 +141,41 @@ public class SPARCNodeMatchRules extends NodeMatchRules { return emitZeroExtendMemory(access, root.getInputBits(), root.getResultBits()); } + @MatchRule("(If (ObjectEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (PointerEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (FloatEquals=compare value LogicCompareAndSwap=cas))") + @MatchRule("(If (IntegerEquals=compare value LogicCompareAndSwap=cas))") + public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) { + JavaConstant constant = value.asJavaConstant(); + assert compare.condition() == Condition.EQ; + if (constant != null && cas.usages().count() == 1) { + long constantValue = constant.asLong(); + boolean successIsTrue; + if (constantValue == 0) { + successIsTrue = false; + } else if (constantValue == 1) { + successIsTrue = true; + } else { + return null; + } + return builder -> { + LIRKind kind = getLirKind(cas); + LabelRef trueLabel = getLIRBlock(root.trueSuccessor()); + LabelRef falseLabel = getLIRBlock(root.falseSuccessor()); + double trueLabelProbability = root.probability(root.trueSuccessor()); + Value expectedValue = operand(cas.getExpectedValue()); + Value newValue = operand(cas.getNewValue()); + SPARCAddressValue address = (SPARCAddressValue) operand(cas.getAddress()); + Condition condition = successIsTrue ? Condition.EQ : Condition.NE; + + Value result = getLIRGeneratorTool().emitValueCompareAndSwap(address, expectedValue, newValue); + getLIRGeneratorTool().emitCompareBranch(kind.getPlatformKind(), result, expectedValue, condition, false, trueLabel, falseLabel, trueLabelProbability); + return null; + }; + } + return null; + } + @Override public SPARCLIRGenerator getLIRGeneratorTool() { return (SPARCLIRGenerator) super.getLIRGeneratorTool(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesCreator.java similarity index 84% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesProvider.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesCreator.java index 62e71409d9a..2770e9cba7b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesCreator.java @@ -24,8 +24,9 @@ package org.graalvm.compiler.core.sparc; import java.util.ListIterator; -import org.graalvm.compiler.java.DefaultSuitesProvider; +import org.graalvm.compiler.java.DefaultSuitesCreator; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.ExpandLogicPhase; @@ -33,14 +34,15 @@ import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.tiers.LowTierContext; import org.graalvm.compiler.phases.tiers.Suites; -public class SPARCSuitesProvider extends DefaultSuitesProvider { - public SPARCSuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) { +public class SPARCSuitesCreator extends DefaultSuitesCreator { + + public SPARCSuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) { super(compilerConfiguration, plugins); } @Override - public Suites createSuites() { - Suites s = super.createSuites(); + public Suites createSuites(OptionValues options) { + Suites s = super.createSuites(options); ListIterator> l = s.getLowTier().findPhase(ExpandLogicPhase.class); while (PhaseSuite.findNextPhase(l, ExpandLogicPhase.class)) { // Search for last occurrence of ExpandLogicPhase diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/AllocSpy.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/AllocSpy.java index 034324a3a4f..095c5c7ab63 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/AllocSpy.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/AllocSpy.java @@ -71,6 +71,7 @@ public final class AllocSpy implements AutoCloseable { field.setAccessible(true); enabled = field.get(null) != null; } catch (Exception e) { + } catch (LinkageError e) { } ENABLED = enabled; if (ENABLED) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java index 03ca1c4136b..4b783878cf8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/BoxingEliminationTest.java @@ -22,10 +22,6 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - import org.graalvm.compiler.loop.DefaultLoopPolicies; import org.graalvm.compiler.loop.phases.LoopPeelingPhase; import org.graalvm.compiler.nodes.ReturnNode; @@ -37,6 +33,9 @@ import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; /** * In the following tests, the usages of local variable "a" are replaced with the integer constant @@ -162,7 +161,7 @@ public class BoxingEliminationTest extends GraalCompilerTest { sum0 = a; } else { int sum = a; - for (int i = 0; i < n; i++) { + for (int i = 1; i < n; i++) { sum += i; } sum0 = sum; @@ -313,7 +312,7 @@ public class BoxingEliminationTest extends GraalCompilerTest { graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); - new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context); + new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context); } private void compareGraphs(final String snippet, final String referenceSnippet) { @@ -331,7 +330,7 @@ public class BoxingEliminationTest extends GraalCompilerTest { } new DeadCodeEliminationPhase().apply(graph); canonicalizer.apply(graph, context); - new PartialEscapePhase(false, canonicalizer).apply(graph, context); + new PartialEscapePhase(false, canonicalizer, graph.getOptions()).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); canonicalizer.apply(graph, context); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ByteBufferTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ByteBufferTest.java new file mode 100644 index 00000000000..bb35d9decad --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ByteBufferTest.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.Collection; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class ByteBufferTest extends GraalCompilerTest { + + class Ret { + + byte byteValue = 0; + short shortValue = 0; + int intValue = 0; + long longValue = 0; + float floatValue = 0.0f; + double doubleValue = 0.0d; + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Ret)) { + return false; + } + + Ret other = (Ret) obj; + if (this.byteValue != other.byteValue) { + return false; + } + if (this.shortValue != other.shortValue) { + return false; + } + if (this.intValue != other.intValue) { + return false; + } + if (this.longValue != other.longValue) { + return false; + } + if (Float.floatToRawIntBits(this.floatValue) != Float.floatToRawIntBits(other.floatValue)) { + return false; + } + if (Double.doubleToRawLongBits(this.doubleValue) != Double.doubleToRawLongBits(other.doubleValue)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public String toString() { + return String.format("0x%02x, 0x%04x, 0x%08x, 0x%04x, 0x%08x", byteValue, shortValue, intValue, Float.floatToRawIntBits(floatValue), Double.doubleToRawLongBits(doubleValue)); + } + } + + @Parameters(name = "{0}") + public static Collection data() { + ArrayList ret = new ArrayList<>(); + ret.add(new Object[]{ByteOrder.BIG_ENDIAN}); + ret.add(new Object[]{ByteOrder.LITTLE_ENDIAN}); + return ret; + } + + @Parameter public ByteOrder byteOrder; + + Ret alignedReadSnippet(byte[] arg) { + ByteBuffer buffer = ByteBuffer.wrap(arg).order(byteOrder); + + Ret ret = new Ret(); + ret.byteValue = buffer.get(); + ret.byteValue += buffer.get(); + ret.shortValue = buffer.getShort(); + ret.intValue = buffer.getInt(); + ret.longValue = buffer.getLong(); + ret.doubleValue = buffer.getDouble(); + ret.floatValue = buffer.getFloat(); + + return ret; + } + + @Test + public void testReadAligned() { + byte[] input = new byte[28]; + for (int i = 0; i < 28; i++) { + input[i] = (byte) (7 * (i + 42)); + } + test("alignedReadSnippet", input); + } + + byte[] alignedWriteSnippet(byte a, byte b, short c, int d, long e, double f, float g) { + byte[] ret = new byte[28]; + ByteBuffer buffer = ByteBuffer.wrap(ret).order(byteOrder); + + buffer.put(a); + buffer.put(b); + buffer.putShort(c); + buffer.putInt(d); + buffer.putLong(e); + buffer.putDouble(f); + buffer.putFloat(g); + + return ret; + } + + @Test + public void testWriteAligned() { + test("alignedWriteSnippet", (byte) 5, (byte) -3, (short) 17, 42, 0x3FC30A25644B7130L, 84.72, 1.23f); + } + + Ret unalignedReadSnippet(byte[] arg) { + ByteBuffer buffer = ByteBuffer.wrap(arg).order(byteOrder); + + Ret ret = new Ret(); + ret.byteValue = buffer.get(); + ret.shortValue = buffer.getShort(); + ret.intValue = buffer.getInt(); + ret.longValue = buffer.getLong(); + ret.doubleValue = buffer.getDouble(); + ret.floatValue = buffer.getFloat(); + + return ret; + } + + @Test + public void testReadUnaligned() { + byte[] input = new byte[27]; + for (int i = 0; i < 27; i++) { + input[i] = (byte) (7 * (i + 42)); + } + test("unalignedReadSnippet", input); + } + + byte[] unalignedWriteSnippet(byte a, short b, int c, long d, double e, float f) { + byte[] ret = new byte[27]; + ByteBuffer buffer = ByteBuffer.wrap(ret).order(byteOrder); + + buffer.put(a); + buffer.putShort(b); + buffer.putInt(c); + buffer.putLong(d); + buffer.putDouble(e); + buffer.putFloat(f); + + return ret; + } + + @Test + public void testWriteUnaligned() { + test("unalignedWriteSnippet", (byte) -3, (short) 17, 42, 0x3FC30A25644B7130L, 84.72, 1.23f); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java index 405652ed1e3..1b932aa68d8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java @@ -22,13 +22,11 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; -import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.INTERCEPT; - import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -41,22 +39,19 @@ import java.util.concurrent.TimeUnit; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Test; - +import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter; +import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter; import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.bytecode.BridgeMethodUtils; import org.graalvm.compiler.core.CompilerThreadFactory; -import org.graalvm.compiler.core.CompilerThreadFactory.DebugConfigAccess; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.type.ArithmeticOpTable; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; -import org.graalvm.compiler.debug.DebugEnvironment; -import org.graalvm.compiler.debug.DelegatingDebugConfig; -import org.graalvm.compiler.debug.GraalDebugConfig; +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.java.GraphBuilderPhase; @@ -67,20 +62,26 @@ import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.VerifyPhase; import org.graalvm.compiler.phases.VerifyPhase.VerificationError; +import org.graalvm.compiler.phases.contract.VerifyNodeCosts; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.phases.verify.VerifyBailoutUsage; import org.graalvm.compiler.phases.verify.VerifyCallerSensitiveMethods; import org.graalvm.compiler.phases.verify.VerifyDebugUsage; +import org.graalvm.compiler.phases.verify.VerifyInstanceOfUsage; import org.graalvm.compiler.phases.verify.VerifyUpdateUsages; import org.graalvm.compiler.phases.verify.VerifyUsageWithEquals; import org.graalvm.compiler.phases.verify.VerifyVirtualizableUsage; import org.graalvm.compiler.runtime.RuntimeProvider; -import org.graalvm.compiler.test.GraalTest; +import org.graalvm.word.LocationIdentity; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.Register; @@ -98,7 +99,15 @@ import jdk.vm.ci.meta.Value; * global invariants such as using {@link Object#equals(Object)} to compare certain types instead of * identity comparisons. */ -public class CheckGraalInvariants extends GraalTest { +public class CheckGraalInvariants extends GraalCompilerTest { + + public CheckGraalInvariants() { + try { + Class.forName("java.lang.management.ManagementFactory"); + } catch (ClassNotFoundException ex) { + Assume.assumeNoException("cannot run without java.management JDK9 module", ex); + } + } private static boolean shouldVerifyEquals(ResolvedJavaMethod m) { if (m.getName().equals("identityEquals")) { @@ -111,17 +120,52 @@ public class CheckGraalInvariants extends GraalTest { return true; } - private static boolean shouldProcess(String classpathEntry) { - if (classpathEntry.endsWith(".jar")) { - String name = new File(classpathEntry).getName(); - return name.contains("jvmci") || name.contains("graal"); + public static String relativeFileName(String absolutePath) { + int lastFileSeparatorIndex = absolutePath.lastIndexOf(File.separator); + return absolutePath.substring(lastFileSeparatorIndex >= 0 ? lastFileSeparatorIndex : 0); + } + + public static class InvariantsTool { + + protected boolean shouldProcess(String classpathEntry) { + if (classpathEntry.endsWith(".jar")) { + String name = new File(classpathEntry).getName(); + return name.contains("jvmci") || name.contains("graal") || name.contains("jdk.internal.vm.compiler"); + } + return false; + } + + protected String getClassPath() { + String bootclasspath; + if (Java8OrEarlier) { + bootclasspath = System.getProperty("sun.boot.class.path"); + } else { + bootclasspath = System.getProperty("jdk.module.path") + File.pathSeparatorChar + System.getProperty("jdk.module.upgrade.path"); + } + return bootclasspath; + } + + protected boolean shouldLoadClass(String className) { + return !className.equals("module-info"); + } + + protected void handleClassLoadingException(Throwable t) { + GraalError.shouldNotReachHere(t); + } + + protected void handleParsingException(Throwable t) { + GraalError.shouldNotReachHere(t); } - return false; } @Test @SuppressWarnings("try") public void test() { + runTest(new InvariantsTool()); + } + + @SuppressWarnings("try") + public static void runTest(InvariantsTool tool) { RuntimeProvider rt = Graal.getRequiredCapability(RuntimeProvider.class); Providers providers = rt.getHostBackend().getProviders(); MetaAccessProvider metaAccess = providers.getMetaAccess(); @@ -134,13 +178,12 @@ public class CheckGraalInvariants extends GraalTest { Assume.assumeTrue(VerifyPhase.class.desiredAssertionStatus()); - String propertyName = Java8OrEarlier ? "sun.boot.class.path" : "jdk.module.path"; - String bootclasspath = System.getProperty(propertyName); - Assert.assertNotNull("Cannot find value of " + propertyName, bootclasspath); + String bootclasspath = tool.getClassPath(); + Assert.assertNotNull("Cannot find boot class path", bootclasspath); final List classNames = new ArrayList<>(); for (String path : bootclasspath.split(File.pathSeparator)) { - if (shouldProcess(path)) { + if (tool.shouldProcess(path)) { try { final ZipFile zipFile = new ZipFile(new File(path)); for (final Enumeration entry = zipFile.entries(); entry.hasMoreElements();) { @@ -148,6 +191,13 @@ public class CheckGraalInvariants extends GraalTest { String name = zipEntry.getName(); if (name.endsWith(".class")) { String className = name.substring(0, name.length() - ".class".length()).replace('/', '.'); + if (isInNativeImage(className)) { + /* + * Native Image is an external tool and does not need to follow the + * Graal invariants. + */ + continue; + } classNames.add(className); } } @@ -162,66 +212,89 @@ public class CheckGraalInvariants extends GraalTest { String property = System.getProperty(CheckGraalInvariants.class.getName() + ".filters"); String[] filters = property == null ? null : property.split(","); - CompilerThreadFactory factory = new CompilerThreadFactory("CheckInvariantsThread", new DebugConfigAccess() { - @Override - public GraalDebugConfig getDebugConfig() { - return DebugEnvironment.initialize(System.out); - } - }); + OptionValues options = getInitialOptions(); + CompilerThreadFactory factory = new CompilerThreadFactory("CheckInvariantsThread"); int availableProcessors = Runtime.getRuntime().availableProcessors(); ThreadPoolExecutor executor = new ThreadPoolExecutor(availableProcessors, availableProcessors, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); List errors = Collections.synchronizedList(new ArrayList<>()); - // Order outer classes before the inner classes - classNames.sort((String a, String b) -> a.compareTo(b)); - // Initialize classes in single thread to avoid deadlocking issues during initialization - List> classes = initializeClasses(classNames); - for (Class c : classes) { - String className = c.getName(); - executor.execute(() -> { - try { - checkClass(c, metaAccess); - } catch (Throwable e) { - errors.add(String.format("Error while checking %s:%n%s", className, printStackTraceToString(e))); - } - }); - for (Method m : c.getDeclaredMethods()) { - if (Modifier.isNative(m.getModifiers()) || Modifier.isAbstract(m.getModifiers())) { - // ignore - } else { - String methodName = className + "." + m.getName(); - if (matches(filters, methodName)) { - executor.execute(() -> { - ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); - try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); Debug.Scope ds = Debug.scope("CheckingGraph", graph, method)) { - graphBuilderSuite.apply(graph, context); - // update phi stamps - graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp); - checkGraph(context, graph); - } catch (VerificationError e) { - errors.add(e.getMessage()); - } catch (LinkageError e) { - // suppress linkages errors resulting from eager resolution - } catch (BailoutException e) { - // Graal bail outs on certain patterns in Java bytecode (e.g., - // unbalanced monitors introduced by jacoco). - } catch (Throwable e) { - errors.add(String.format("Error while checking %s:%n%s", methodName, printStackTraceToString(e))); - } - }); - } + for (Method m : BadUsageWithEquals.class.getDeclaredMethods()) { + ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); + try (DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER)) { + StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).method(method).build(); + try (DebugCloseable s = debug.disableIntercept(); DebugContext.Scope ds = debug.scope("CheckingGraph", graph, method)) { + graphBuilderSuite.apply(graph, context); + // update phi stamps + graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp); + checkGraph(context, graph); + errors.add(String.format("Expected error while checking %s", m)); + } catch (VerificationError e) { + // expected! + } catch (Throwable e) { + errors.add(String.format("Error while checking %s:%n%s", m, printStackTraceToString(e))); } } } - executor.shutdown(); - try { - executor.awaitTermination(1, TimeUnit.HOURS); - } catch (InterruptedException e1) { - throw new RuntimeException(e1); - } + if (errors.isEmpty()) { + // Order outer classes before the inner classes + classNames.sort((String a, String b) -> a.compareTo(b)); + // Initialize classes in single thread to avoid deadlocking issues during initialization + List> classes = initializeClasses(tool, classNames); + for (Class c : classes) { + String className = c.getName(); + executor.execute(() -> { + try { + checkClass(c, metaAccess); + } catch (Throwable e) { + errors.add(String.format("Error while checking %s:%n%s", className, printStackTraceToString(e))); + } + }); + for (Method m : c.getDeclaredMethods()) { + if (Modifier.isNative(m.getModifiers()) || Modifier.isAbstract(m.getModifiers())) { + // ignore + } else { + String methodName = className + "." + m.getName(); + if (matches(filters, methodName)) { + executor.execute(() -> { + try (DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER)) { + ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build(); + try (DebugCloseable s = debug.disableIntercept(); DebugContext.Scope ds = debug.scope("CheckingGraph", graph, method)) { + checkMethod(method); + graphBuilderSuite.apply(graph, context); + // update phi stamps + graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp); + checkGraph(context, graph); + } catch (VerificationError e) { + errors.add(e.getMessage()); + } catch (LinkageError e) { + // suppress linkages errors resulting from eager resolution + } catch (BailoutException e) { + // Graal bail outs on certain patterns in Java bytecode + // (e.g., + // unbalanced monitors introduced by jacoco). + } catch (Throwable e) { + try { + tool.handleParsingException(e); + } catch (Throwable t) { + errors.add(String.format("Error while checking %s:%n%s", methodName, printStackTraceToString(e))); + } + } + } + }); + } + } + } + } + executor.shutdown(); + try { + executor.awaitTermination(1, TimeUnit.HOURS); + } catch (InterruptedException e1) { + throw new RuntimeException(e1); + } + } if (!errors.isEmpty()) { StringBuilder msg = new StringBuilder(); String nl = String.format("%n"); @@ -235,17 +308,21 @@ public class CheckGraalInvariants extends GraalTest { } } - private static List> initializeClasses(List classNames) { + private static boolean isInNativeImage(String className) { + return className.startsWith("org.graalvm.nativeimage"); + } + + private static List> initializeClasses(InvariantsTool tool, List classNames) { List> classes = new ArrayList<>(classNames.size()); for (String className : classNames) { - if (className.equals("module-info")) { + if (!tool.shouldLoadClass(className)) { continue; } try { Class c = Class.forName(className, true, CheckGraalInvariants.class.getClassLoader()); classes.add(c); - } catch (ClassNotFoundException e) { - e.printStackTrace(); + } catch (Throwable t) { + tool.handleClassLoadingException(t); } } return classes; @@ -259,6 +336,24 @@ public class CheckGraalInvariants extends GraalTest { if (c.getAnnotation(NodeInfo.class) == null) { throw new AssertionError(String.format("Node subclass %s requires %s annotation", c.getName(), NodeClass.class.getSimpleName())); } + VerifyNodeCosts.verifyNodeClass(c); + } + } + + private static void checkMethod(ResolvedJavaMethod method) { + if (method.getAnnotation(Snippet.class) == null) { + Annotation[][] parameterAnnotations = method.getParameterAnnotations(); + for (int i = 0; i < parameterAnnotations.length; i++) { + for (Annotation a : parameterAnnotations[i]) { + Class annotationType = a.annotationType(); + if (annotationType == ConstantParameter.class || annotationType == VarargsParameter.class || annotationType == NonNullParameter.class) { + VerificationError verificationError = new VerificationError("Parameter %d of %s is annotated with %s but the method is not annotated with %s", i, method, + annotationType.getSimpleName(), + Snippet.class.getSimpleName()); + throw verificationError; + } + } + } } } @@ -267,6 +362,8 @@ public class CheckGraalInvariants extends GraalTest { */ private static void checkGraph(HighTierContext context, StructuredGraph graph) { if (shouldVerifyEquals(graph.method())) { + // If you add a new type to test here, be sure to add appropriate + // methods to the BadUsageWithEquals class below new VerifyUsageWithEquals(Value.class).apply(graph, context); new VerifyUsageWithEquals(Register.class).apply(graph, context); new VerifyUsageWithEquals(RegisterCategory.class).apply(graph, context); @@ -283,6 +380,7 @@ public class CheckGraalInvariants extends GraalTest { new VerifyVirtualizableUsage().apply(graph, context); new VerifyUpdateUsages().apply(graph, context); new VerifyBailoutUsage().apply(graph, context); + new VerifyInstanceOfUsage().apply(graph, context); if (graph.method().isBridge()) { BridgeMethodUtils.getBridgedMethod(graph.method()); } @@ -305,4 +403,108 @@ public class CheckGraalInvariants extends GraalTest { t.printStackTrace(new PrintWriter(sw)); return sw.toString(); } + + static class BadUsageWithEquals { + Value aValue; + Register aRegister; + RegisterCategory aRegisterCategory; + JavaType aJavaType; + JavaField aJavaField; + JavaMethod aJavaMethod; + LocationIdentity aLocationIdentity; + LIRKind aLIRKind; + ArithmeticOpTable anArithmeticOpTable; + ArithmeticOpTable.Op anArithmeticOpTableOp; + + static Value aStaticValue; + static Register aStaticRegister; + static RegisterCategory aStaticRegisterCategory; + static JavaType aStaticJavaType; + static JavaField aStaticJavaField; + static JavaMethod aStaticJavaMethod; + static LocationIdentity aStaticLocationIdentity; + static LIRKind aStaticLIRKind; + static ArithmeticOpTable aStaticArithmeticOpTable; + static ArithmeticOpTable.Op aStaticArithmeticOpTableOp; + + boolean test01(Value f) { + return aValue == f; + } + + boolean test02(Register f) { + return aRegister == f; + } + + boolean test03(RegisterCategory f) { + return aRegisterCategory == f; + } + + boolean test04(JavaType f) { + return aJavaType == f; + } + + boolean test05(JavaField f) { + return aJavaField == f; + } + + boolean test06(JavaMethod f) { + return aJavaMethod == f; + } + + boolean test07(LocationIdentity f) { + return aLocationIdentity == f; + } + + boolean test08(LIRKind f) { + return aLIRKind == f; + } + + boolean test09(ArithmeticOpTable f) { + return anArithmeticOpTable == f; + } + + boolean test10(ArithmeticOpTable.Op f) { + return anArithmeticOpTableOp == f; + } + + boolean test12(Value f) { + return aStaticValue == f; + } + + boolean test13(Register f) { + return aStaticRegister == f; + } + + boolean test14(RegisterCategory f) { + return aStaticRegisterCategory == f; + } + + boolean test15(JavaType f) { + return aStaticJavaType == f; + } + + boolean test16(JavaField f) { + return aStaticJavaField == f; + } + + boolean test17(JavaMethod f) { + return aStaticJavaMethod == f; + } + + boolean test18(LocationIdentity f) { + return aStaticLocationIdentity == f; + } + + boolean test19(LIRKind f) { + return aStaticLIRKind == f; + } + + boolean test20(ArithmeticOpTable f) { + return aStaticArithmeticOpTable == f; + } + + boolean test21(ArithmeticOpTable.Op f) { + return aStaticArithmeticOpTableOp == f; + } + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CommonedConstantsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CommonedConstantsTest.java index 85cf35b70ce..7b5d173b407 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CommonedConstantsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CommonedConstantsTest.java @@ -90,7 +90,7 @@ public class CommonedConstantsTest extends GraalCompilerTest { @Test public void test1() { - getSuites().getHighTier().findPhase(AbstractInliningPhase.class).remove(); + createSuites(getInitialOptions()).getHighTier().findPhase(AbstractInliningPhase.class).remove(); test1Snippet(new String(alphabet)); test("test1Snippet", (Object) null); @@ -114,7 +114,7 @@ public class CommonedConstantsTest extends GraalCompilerTest { @Test public void test2() { - assert getSuites().getHighTier().findPhase(AbstractInliningPhase.class).hasNext(); + assert createSuites(getInitialOptions()).getHighTier().findPhase(AbstractInliningPhase.class).hasNext(); test2Snippet(new String(alphabet)); test("test2Snippet", (Object) null); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java new file mode 100644 index 00000000000..81331104a9c --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest2.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import static org.graalvm.compiler.graph.test.matchers.NodeIterableIsEmpty.isNotEmpty; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.calc.IntegerLessThanNode; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Test; + +public class CompareCanonicalizerTest2 extends GraalCompilerTest { + + @SuppressWarnings("unused") private static int sink0; + @SuppressWarnings("unused") private static int sink1; + + private StructuredGraph getCanonicalizedGraph(String name) { + StructuredGraph graph = parseEager(name, AllowAssumptions.YES); + new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); + return graph; + } + + public void testIntegerTestCanonicalization(String name) { + StructuredGraph graph = getCanonicalizedGraph(name); + Assert.assertThat(graph.getNodes().filter(IntegerLessThanNode.class), isNotEmpty()); + } + + @Test + public void test0() { + testIntegerTestCanonicalization("integerTestCanonicalization0"); + } + + @Test + public void test1() { + testIntegerTestCanonicalization("integerTestCanonicalization1"); + } + + public static void integerTestCanonicalization0(int a) { + if (1 < a + 1) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void integerTestCanonicalization1(int a) { + if (a - 1 < -1) { + sink1 = 0; + } else { + sink0 = -1; + } + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest3.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest3.java new file mode 100644 index 00000000000..ba296576c03 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CompareCanonicalizerTest3.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; +import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Ignore; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +public class CompareCanonicalizerTest3 extends GraalCompilerTest { + + @SuppressWarnings("unused") private static int sink0; + @SuppressWarnings("unused") private static int sink1; + + @Test + public void test00() { + assertCanonicallyEqual("integerTestCanonicalization00", "referenceSnippet00"); + } + + public static void integerTestCanonicalization00(char a) { + if (a - 1 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @SuppressWarnings("unused") + public static void referenceSnippet00(char a) { + sink1 = 0; + } + + @Ignore("Needs better stamp support for unsigned ranges") + @Test + public void test01() { + assertCanonicallyEqual("integerTestCanonicalization01", "referenceSnippet01"); + } + + public static void integerTestCanonicalization01(char a) { + if (Integer.compareUnsigned(a - 1, a) < 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet01(char a) { + if (a != 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Ignore("Needs better stamp support for unsigned ranges") + @Test + public void test1() { + assertCanonicallyEqual("integerTestCanonicalization1", "referenceSnippet1"); + } + + public static void integerTestCanonicalization1(char a) { + if (Integer.compareUnsigned(a - 2, a) < 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet1(char a) { + if (Integer.compareUnsigned(a, 2) >= 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test2() { + assertCanonicallyEqual("integerTestCanonicalization2", "referenceSnippet2"); + } + + public static void integerTestCanonicalization2(int a) { + if (a - 1 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet2(int a) { + if (a != Integer.MIN_VALUE) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test3() { + assertCanonicallyEqual("integerTestCanonicalization3", "referenceSnippet3"); + } + + public static void integerTestCanonicalization3(int a) { + if (a - 2 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet3(int a) { + if (a >= Integer.MIN_VALUE + 2) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test4() { + assertCanonicallyEqual("integerTestCanonicalization4", "referenceSnippet4"); + } + + public static void integerTestCanonicalization4(int a) { + if (a + 1 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet4(int a) { + if (a == Integer.MAX_VALUE) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test5() { + assertCanonicallyEqual("integerTestCanonicalization5", "referenceSnippet5"); + } + + public static void integerTestCanonicalization5(int a) { + if (a + 2 < a) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet5(int a) { + if (a > Integer.MAX_VALUE - 2) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test6() { + assertCanonicallyEqual("integerTestCanonicalization6", "referenceSnippet6"); + } + + public static void integerTestCanonicalization6(int a) { + if (a < a + 1) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet6(int a) { + if (a != Integer.MAX_VALUE) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test7() { + assertCanonicallyEqual("integerTestCanonicalization7", "referenceSnippet7"); + } + + public static void integerTestCanonicalization7(int a) { + if (a < a + 2) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet7(int a) { + if (a <= Integer.MAX_VALUE - 2) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + protected void assertCanonicallyEqual(String snippet, String reference) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + PhaseContext context = new PhaseContext(getProviders()); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + canonicalizer.apply(graph, context); + canonicalizer.apply(graph, context); + StructuredGraph referenceGraph = parseEager(reference, AllowAssumptions.YES); + canonicalizer.apply(referenceGraph, context); + canonicalizer.apply(referenceGraph, context); + assertEquals(referenceGraph, graph, true, true); + } + + @Override + protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { + return InlineInvokePlugin.InlineInfo.createStandardInlineInfo(method); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionTest.java index 1048d725105..d58022e16bd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionTest.java @@ -28,11 +28,10 @@ import static org.junit.Assert.assertTrue; import java.util.Random; -import jdk.vm.ci.meta.JavaConstant; - +import org.graalvm.compiler.core.common.calc.Condition; import org.junit.Test; -import org.graalvm.compiler.core.common.calc.Condition; +import jdk.vm.ci.meta.JavaConstant; public class ConditionTest { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationLoadFieldConstantFoldTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationLoadFieldConstantFoldTest.java deleted file mode 100644 index b27daf302ee..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationLoadFieldConstantFoldTest.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.test; - -import java.lang.reflect.Field; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.nodes.IfNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; -import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; - -import sun.misc.Unsafe; - -public class ConditionalEliminationLoadFieldConstantFoldTest extends GraalCompilerTest { - public static int intSideEffect; - - public static final B FinalField = new B(10); - - private abstract static class A { - - } - - private static class B extends A { - final int a; - - B(int a) { - this.a = a; - } - } - - private static class C extends A { - final B b; - - C(B b) { - this.b = b; - } - } - - private static class D extends A { - final C c; - - D(C c) { - this.c = c; - } - } - - private static class E extends D { - final Object o; - - E(C c, Object o) { - super(c); - this.o = o; - } - } - - public static final B CONST_B = new B(10); - public static final C CONST_C = new C(CONST_B); - public static final D CONST_D = new D(CONST_C); - - public int testReadConstInBranch(B b) { - if (b == CONST_B) { - if (b.a == 5) { - intSideEffect = b.a; - } else { - intSideEffect = 10; - } - } - return 0; - } - - public int testMultipleReadsConstInBranch(D d) { - if (d == CONST_D) { - C c = d.c; - B b = c.b; - int res = b.a + 12; - if (res == 125) { - intSideEffect = 12; - } - } - return 0; - } - - public int testLoadFinalInstanceOf(E e) { - Object o = e.o; - if (o == CONST_C) { - if (o instanceof A) { - // eliminate, implied by a.x == Const(Subclass) - intSideEffect = 1; - } else { - intSideEffect = 10; - } - } - return 0; - } - - public int testLoadFinalTwiceInstanceOf(E e) { - if (e.o == CONST_C) { - if (e.o instanceof A) { - intSideEffect = 1; - } else { - intSideEffect = 10; - } - } - return 0; - } - - static class C1 { - final int a; - - C1(int a) { - this.a = a; - } - } - - static class C2 { - final C1 c1; - - C2(C1 c1) { - this.c1 = c1; - } - } - - public static int foldThatIsNotAllowed(C2 c2) { - // read before, this will be used to load through when folding - C1 c1Unknown = c2.c1; - - // be naughty (will be a store field after canonicalization as it has a constant offset, so - // we would be able to eliminate the inner if after an early read elimination but we would - // fold before and ce the inner if already) - // - // note: if the offset would not be constant but a parameter we would not even be able to - // remove in inner most if as we cannot rewrite the unsafe store to a store field node as - // the store might kill ANY_LOCATION - UNSAFE.putObject(c2, C2_C1_OFFSET, C1_AFTER_READ_CONST); - - if (c2 == C2_CONST) { - if (c1Unknown == C1_CONST) { - /* - * This if can be eliminated (as we rewrite the unsafe store with a constant offset - * to a store field node) but the remaining branch must be the false branch. If we - * do not fold through both field loads we will canonicalize the unsafe store to a - * store field, see the new value and can thus eliminate the true branch - * - * if we fold through the load fields we would load from the object read before the - * store so we miss the unsafe update - */ - if (c2.c1.a == 10) { - intSideEffect = 1; - return 1; - } else { - intSideEffect = 2; - return 2; - } - } else { - intSideEffect = -2; - return -2; - } - } else { - intSideEffect = -1; - return -1; - } - } - - public int testLoadFinalTwiceNoReadEliminationInstanceOf(E e) { - if (e.o == CONST_C) { - /* - * we cannot eliminate the second read of e.o although it is a final field. the call to - * System.gc (or any other memory checkpoint killing ANY_LOCATION) will prohibit the - * elimination of the second load, thus we have two different load nodes, we know that - * that first load field is a constant but we do not know for the second one, assuming - * e.o is final, as it might have been written in between - * - * this prohibits us to remove the if (fold through all loads to final fields) and the - * instance of e.o - */ - System.gc(); - C c = (C) e.o; - if (c.b.a == 10) { - intSideEffect = 1; - } else { - intSideEffect = 10; - } - } - return 0; - - } - - private static final C1 C1_CONST = new C1(0); - private static final C2 C2_CONST = new C2(C1_CONST); - private static final C1 C1_AFTER_READ_CONST = new C1(10); - - private static Unsafe getUnsafe() { - try { - return Unsafe.getUnsafe(); - } catch (SecurityException e) { - } - try { - Field theUnsafeInstance = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafeInstance.setAccessible(true); - return (Unsafe) theUnsafeInstance.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("exception while trying to get Unsafe.theUnsafe via reflection:", e); - } - } - - private static final sun.misc.Unsafe UNSAFE = getUnsafe(); - private static final long C2_C1_OFFSET; - - static { - try { - Field f = C2.class.getDeclaredField("c1"); - C2_C1_OFFSET = UNSAFE.objectFieldOffset(f); - } catch (NoSuchFieldException | SecurityException e) { - throw new RuntimeException(e); - } - } - - @Test - public void test01() { - checkGraph("testReadConstInBranch", 1); - test("testReadConstInBranch", new B(1)); - } - - @Test - public void test02() { - checkGraph("testMultipleReadsConstInBranch", 1); - } - - @Test - public void test03() { - checkGraph("testLoadFinalInstanceOf", 1); - } - - @Test - public void test04() { - checkGraph("testLoadFinalTwiceInstanceOf", 1); - } - - @Test - public void test05() { - checkGraph("testLoadFinalTwiceNoReadEliminationInstanceOf", 2); - } - - @Test(expected = AssertionError.class) - @SuppressWarnings("try") - public void test06() { - Result actual = executeActual(getResolvedJavaMethod("foldThatIsNotAllowed"), null, C2_CONST); - UNSAFE.putObject(C2_CONST, C2_C1_OFFSET, C1_CONST); - Result expected = executeExpected(getResolvedJavaMethod("foldThatIsNotAllowed"), null, C2_CONST); - Assert.assertEquals(expected.returnValue, actual.returnValue); - } - - @SuppressWarnings("try") - private StructuredGraph checkGraph(String name, int nrOfIfsAfter) { - StructuredGraph g = parseForCompile(getResolvedJavaMethod(name)); - CanonicalizerPhase c = new CanonicalizerPhase(); - c.apply(g, getDefaultHighTierContext()); - new EarlyReadEliminationPhase(c).apply(g, getDefaultHighTierContext()); - new IterativeConditionalEliminationPhase(c, false).apply(g, getDefaultHighTierContext()); - Assert.assertEquals("Nr of Ifs left does not match", nrOfIfsAfter, g.getNodes().filter(IfNode.class).count()); - c.apply(g, getDefaultHighTierContext()); - return g; - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java index 5f8b980e0a9..01a0236d309 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationMulTest.java @@ -22,19 +22,18 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase; +import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Test; public class ConditionalEliminationMulTest extends GraalCompilerTest { public static void snippet01(int a) { - if (a == 2) { - if (a * 3 != 6) { + if (a == 3) { + if (a * 11 != 33) { shouldBeOptimizedAway(); } } @@ -42,7 +41,7 @@ public class ConditionalEliminationMulTest extends GraalCompilerTest { public static void snippet02(int a) { if (a == 0) { - if (a * 3 != 0) { + if (a * 11 != 0) { shouldBeOptimizedAway(); } } @@ -76,11 +75,11 @@ public class ConditionalEliminationMulTest extends GraalCompilerTest { private StructuredGraph prepareGraph(String snippet) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); + new ConditionalEliminationPhase(false).apply(graph, context); CanonicalizerPhase c = new CanonicalizerPhase(); c.apply(graph, context); - new DominatorConditionalEliminationPhase(false).apply(graph, context); + new ConditionalEliminationPhase(false).apply(graph, context); c.apply(graph, context); return graph; } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest1.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest1.java index 73a3b98d8fc..f79580e9be4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest1.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest1.java @@ -22,25 +22,24 @@ */ package org.graalvm.compiler.core.test; +import org.graalvm.compiler.api.directives.GraalDirectives; import org.junit.Test; -import org.graalvm.compiler.api.directives.GraalDirectives; - /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase { + protected static int sink3; private static final String REFERENCE_SNIPPET = "referenceSnippet"; @SuppressWarnings("all") - public static int referenceSnippet(int a) { + public static void referenceSnippet(int a) { if (a == 0) { - return 1; + sink1 = 1; } - return 0; + sink0 = 0; } @Test @@ -49,21 +48,21 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase } @SuppressWarnings("all") - public static int test1Snippet(int a) { + public static void test1Snippet(int a) { if (a == 0) { if (a == 5) { - return 100; + sink2 = 100; } if (a > 100) { if (a == 0) { - return 200; + sink3 = 200; } } if (a != 2) { - return 1; + sink1 = 1; } } - return 0; + sink0 = 0; } @Test @@ -72,18 +71,18 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase } @SuppressWarnings("all") - public static int test2Snippet(int a) { + public static void test2Snippet(int a) { if (a == 0) { if (a > 100) { if (a == 0) { - return 200; + sink3 = 200; } } if (a != 2) { - return 1; + sink1 = 1; } } - return 0; + sink0 = 0; } @Test @@ -92,7 +91,7 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase } @SuppressWarnings("all") - public static int test3Snippet(int a) { + public static void test3Snippet(int a) { if (a == 0) { if (a < 1) { if (a < 2) { @@ -101,9 +100,9 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase if (a > -2) { if (a > -3) { if (a == 1) { - return 42; + sink2 = 42; } else { - return 1; + sink1 = 1; } } } @@ -112,18 +111,18 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase } } } - return 0; + sink0 = 0; } @SuppressWarnings("all") - public static int test4Snippet(int a, int b) { + public static void test4Snippet(int a, int b) { if (b < 1) { GraalDirectives.controlFlowAnchor(); if (b < 0) { - return 1; + sink1 = 1; } } - return 0; + sink0 = 0; } @Test @@ -132,21 +131,21 @@ public class ConditionalEliminationTest1 extends ConditionalEliminationTestBase } @SuppressWarnings("all") - public static int test5Snippet(int a, int b) { + public static void test5Snippet(int a, int b) { if ((b & 3) == 0) { GraalDirectives.controlFlowAnchor(); if ((b & 7) == 0) { GraalDirectives.controlFlowAnchor(); - return 1; + sink1 = 1; } } else { GraalDirectives.controlFlowAnchor(); if ((b & 1) == 0) { GraalDirectives.controlFlowAnchor(); - return 2; + sink2 = 2; } } - return 0; + sink0 = 0; } @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java index 30f8db587bb..2a79042f360 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest10.java @@ -22,36 +22,38 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.nodes.GuardNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Test; /** * This test checks the combined action of - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} and + * {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} and * {@link org.graalvm.compiler.phases.common.LoweringPhase}. The lowering phase needs to introduce * the null checks at the correct places for the dominator conditional elimination phase to pick * them up. */ public class ConditionalEliminationTest10 extends ConditionalEliminationTestBase { + private static boolean condition1; + private static boolean condition2; + private static class TestClass { int x; } @SuppressWarnings("all") - public static int testSnippet(int a, TestClass t) { + public static int testSnippet1(TestClass t) { int result = 0; - if (a == 0) { + if (condition1) { GraalDirectives.controlFlowAnchor(); result = t.x; } @@ -61,11 +63,38 @@ public class ConditionalEliminationTest10 extends ConditionalEliminationTestBase @Test public void test1() { - StructuredGraph graph = parseEager("testSnippet", AllowAssumptions.YES); + test("testSnippet1", 1); + } + + @SuppressWarnings("all") + public static int testSnippet2(TestClass t) { + int result = 0; + if (condition1) { + GraalDirectives.controlFlowAnchor(); + result = t.x; + } else { + GraalDirectives.controlFlowAnchor(); + result = t.x; + } + + if (condition2) { + result = t.x; + GraalDirectives.controlFlowAnchor(); + } + + return result; + } + + @Test + public void test2() { + test("testSnippet2", 1); + } + + private void test(String snippet, int guardCount) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); PhaseContext context = new PhaseContext(getProviders()); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - Assert.assertEquals(2, graph.getNodes().filter(GuardNode.class).count()); - new DominatorConditionalEliminationPhase(true).apply(graph, context); - Assert.assertEquals(1, graph.getNodes().filter(GuardNode.class).count()); + new ConditionalEliminationPhase(true).apply(graph, context); + Assert.assertEquals(guardCount, graph.getNodes().filter(GuardNode.class).count()); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java index 5c2b861ef15..6978bcfb669 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest11.java @@ -22,26 +22,19 @@ */ package org.graalvm.compiler.core.test; +import org.graalvm.compiler.api.directives.GraalDirectives; import org.junit.Ignore; import org.junit.Test; -import org.graalvm.compiler.api.directives.GraalDirectives; - /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase { - public ConditionalEliminationTest11() { - // Don't disable simplification - super(false); - } - @SuppressWarnings("all") public static int referenceSnippet(int a) { if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -54,10 +47,10 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase @SuppressWarnings("all") public static int test1Snippet(int a) { if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -65,10 +58,10 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase @SuppressWarnings("all") public static int test2Snippet(int a) { if ((a & 8) == 0) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -81,10 +74,10 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase @SuppressWarnings("all") public static int test3Snippet(int a) { if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -98,10 +91,10 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase @SuppressWarnings("all") public static int test4Snippet(int a) { if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) == 0) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } @@ -114,7 +107,7 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test5Snippet(int a) { if ((a & 5) == 5) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 7) != 0) { return 0; @@ -130,19 +123,19 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test6Snippet(int a) { if ((a & 8) != 0) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 15) != 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return 0; } public static int reference6Snippet(int a) { if ((a & 8) != 0) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); return 0; } @@ -153,17 +146,17 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test7Snippet(int a) { if ((a & 15) == 15) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) == 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } public static int reference7Snippet(int a) { if ((a & 8) == 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } @@ -175,20 +168,20 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test8Snippet(int a) { if ((a & 16) == 16) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 44) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } public static int reference8Snippet(int a) { if ((a & 60) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } @@ -201,23 +194,23 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int test9Snippet(int a) { if ((a & 16) == 16) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 44) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if (a != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } public static int reference9Snippet(int a) { if (a != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return a; } @@ -239,16 +232,16 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase int v = b.byteValue(); long a = v & 0xffffffff; if (v != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 16) == 16) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 44) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return v; @@ -257,12 +250,13 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int reference10Snippet(ByteHolder b) { byte v = b.byteValue(); if (v != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return v; } @Test + @Ignore public void test10() { testConditionalElimination("test10Snippet", "reference10Snippet"); } @@ -272,16 +266,16 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase long a = v & 0xffffffff; if ((a & 16) == 16) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 8) != 8) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if ((a & 44) != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if (v != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return v; } @@ -289,12 +283,13 @@ public class ConditionalEliminationTest11 extends ConditionalEliminationTestBase public static int reference11Snippet(ByteHolder b) { byte v = b.byteValue(); if (v != 44) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } return v; } @Test + @Ignore public void test11() { testConditionalElimination("test11Snippet", "reference11Snippet"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest12.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest12.java new file mode 100644 index 00000000000..fb1cf057578 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest12.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.junit.Test; + +public class ConditionalEliminationTest12 extends ConditionalEliminationTestBase { + + static class A { + + } + + static class B extends A { + + } + + static class C extends B { + + } + + static class D extends C { + + } + + @SuppressWarnings({"static-method", "unused"}) + private int referenceMethod(Object a) { + if (a instanceof A) { + if (a instanceof C) { + return 1; + } else { + GraalDirectives.deoptimizeAndInvalidate(); + } + } + return 0; + } + + @SuppressWarnings({"static-method", "unused"}) + private int testMethod(Object a) { + if (a instanceof A) { + if (a instanceof C) { + if (a instanceof B) { + B b = (B) a; + if (b instanceof C) { + return 1; + } else { + GraalDirectives.deoptimizeAndInvalidate(); + } + } + } else { + GraalDirectives.deoptimizeAndInvalidate(); + } + } + return 0; + } + + @SuppressWarnings("unused") + @Test + public void testFloatingGuards() { + // Make sure class D is loaded. + D d = new D(); + testConditionalElimination("testMethod", "referenceMethod"); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java new file mode 100644 index 00000000000..68e5979acba --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest13.java @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; +import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; + +public class ConditionalEliminationTest13 extends ConditionalEliminationTestBase { + + @Override + protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) { + return InlineInvokePlugin.InlineInfo.createStandardInlineInfo(method); + } + + public static void referenceSnippet1(int a) { + if (Integer.compareUnsigned(a, a + 1) < 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet1(int a) { + if (Integer.compareUnsigned(a, a + 1) < 0 || a == 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet2(int a) { + if (0 < a) { + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet2(int a) { + if (0 < a) { + if (a == -1) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet3(int a) { + if (0 < a) { + if (a == 1) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + @SuppressWarnings("unused") + public static void referenceSnippet4(int a) { + sink1 = 0; + } + + public static void testSnippet4(int a) { + if (Integer.compareUnsigned(a - 1, a) < 0 || a == 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet5(int a) { + if (a < 0) { + if (a == -1) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void referenceSnippet6(int a) { + if (a < 0) { + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet6(int a) { + if (a < 0) { + if (a == 0) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet7(int a) { + if (0 < a) { + if (a == 0) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet8(int a) { + if (Integer.compareUnsigned(a, a + 1) < 0 || a == 0xffff_ffff) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet9(int a) { + if (Integer.compareUnsigned(a - 1, a) < 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet9(int a) { + if (Integer.compareUnsigned(a - 1, a) < 0 || a == 0xffff_ffff) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + private static int either(int a, int b) { + return (sink0 + sink1 + sink2) == 0 ? a : b; + } + + public static void testSnippet10(int a) { + if (Integer.compareUnsigned(a, a + either(1, 2)) < 0 || a == 0xffff_ffff || a == 0xffff_fffe) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet11(int a) { + if (Integer.compareUnsigned(a, Integer.MAX_VALUE + 1) > 0) { + sink1 = 0; + } + sink0 = -1; + } + + public static void testSnippet11(int a) { + if (Integer.compareUnsigned(a, Integer.MAX_VALUE + 1) > 0) { + if (Integer.compareUnsigned(a, 42) <= 0) { + sink2 = -2; + } + sink1 = 0; + } + sink0 = -1; + } + + public static void referenceSnippet12(int a) { + if (Integer.compareUnsigned(a, 0xffff_ffff) >= 0) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet12(int a) { + if (Integer.compareUnsigned(a, 0xffff_ffff) >= 0 && a == 0xffff_ffff) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet13(int a) { + int x = either(0, 1); + if (a <= a + x) { + if (a == Integer.MAX_VALUE) { + sink2 = -2; + } + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void referenceSnippet14(int a) { + int x = either(0, 1); + if (a < a + x) { + sink1 = 0; + } else { + sink0 = -1; + } + } + + public static void testSnippet14(int a) { + int x = either(0, 1); + if (a < a + x) { + if (a == Integer.MAX_VALUE) { + sink2 = -2; + } + sink1 = 0; + } else { + sink0 = -1; + } + } + + @Test + public void test1() { + testConditionalElimination("testSnippet1", "referenceSnippet1"); + } + + @Test + public void test2() { + testConditionalElimination("testSnippet2", "referenceSnippet2"); + } + + @Test + public void test3() { + testConditionalElimination("testSnippet3", "testSnippet3"); + } + + @Test + public void test4() { + testConditionalElimination("testSnippet4", "referenceSnippet4"); + } + + @Test + public void test5() { + testConditionalElimination("testSnippet5", "testSnippet5"); + } + + @Test + public void test6() { + testConditionalElimination("testSnippet6", "referenceSnippet6"); + } + + @Test + public void test7() { + testConditionalElimination("testSnippet7", "referenceSnippet2"); + } + + @Test + public void test8() { + testConditionalElimination("testSnippet8", "referenceSnippet4"); + } + + @Test + public void test9() { + testConditionalElimination("testSnippet9", "referenceSnippet9"); + } + + @Test + public void test10() { + testConditionalElimination("testSnippet10", "referenceSnippet4"); + } + + @Test + public void test11() { + testConditionalElimination("testSnippet11", "referenceSnippet11"); + } + + @Test + public void test12() { + testConditionalElimination("testSnippet12", "referenceSnippet12"); + } + + @Test + public void test13() { + testConditionalElimination("testSnippet13", "testSnippet13"); + } + + @Test + public void test14() { + testConditionalElimination("testSnippet14", "referenceSnippet14"); + } + + @Override + protected void prepareGraph(StructuredGraph graph, CanonicalizerPhase canonicalizer, PhaseContext context, boolean applyLowering) { + super.prepareGraph(graph, canonicalizer, context, applyLowering); + graph.clearAllStateAfter(); + graph.setGuardsStage(StructuredGraph.GuardsStage.AFTER_FSA); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After preparation"); + canonicalizer.apply(graph, context); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java index 0e9604496b8..d1b7a123b69 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest2.java @@ -22,22 +22,20 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - import org.graalvm.compiler.nodes.GuardNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest2 extends ConditionalEliminationTestBase { @@ -103,7 +101,7 @@ public class ConditionalEliminationTest2 extends ConditionalEliminationTestBase new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); new FloatingReadPhase().apply(graph); - new DominatorConditionalEliminationPhase(true).apply(graph, context); + new ConditionalEliminationPhase(true).apply(graph, context); canonicalizer.apply(graph, context); assertDeepEquals(1, graph.getNodes().filter(GuardNode.class).count()); @@ -125,7 +123,7 @@ public class ConditionalEliminationTest2 extends ConditionalEliminationTestBase new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); - new DominatorConditionalEliminationPhase(true).apply(graph, context); + new ConditionalEliminationPhase(true).apply(graph, context); canonicalizer.apply(graph, context); assertDeepEquals(0, graph.getNodes().filter(GuardNode.class).count()); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest3.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest3.java index ef8d7c7e650..31273f5ce63 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest3.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest3.java @@ -22,13 +22,14 @@ */ package org.graalvm.compiler.core.test; +import org.junit.Ignore; import org.junit.Test; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ +@Ignore public class ConditionalEliminationTest3 extends ConditionalEliminationTestBase { private static final String REFERENCE_SNIPPET = "referenceSnippet"; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest4.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest4.java index 1daf7a5b552..db409dd3d43 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest4.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest4.java @@ -25,9 +25,8 @@ package org.graalvm.compiler.core.test; import org.junit.Test; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest4 extends ConditionalEliminationTestBase { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java index 255e5a87ec7..a32acfbbf21 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest5.java @@ -22,14 +22,13 @@ */ package org.graalvm.compiler.core.test; +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.junit.Ignore; import org.junit.Test; -import org.graalvm.compiler.api.directives.GraalDirectives; - /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase { @@ -39,26 +38,30 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase interface B extends A { } + interface C extends B { + + } + static final class DistinctA { } static final class DistinctB { } - public static int reference1Snippet(Object a) { + public static void reference1Snippet(Object a) { if (a instanceof B) { - return 1; + sink1 = 1; } - return 2; + sink2 = 2; } - public static int test1Snippet(Object a) { + public static void test1Snippet(Object a) { if (a instanceof B) { if (a instanceof A) { - return 1; + sink1 = 1; } } - return 2; + sink2 = 2; } @Test @@ -66,21 +69,21 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase testConditionalElimination("test1Snippet", "reference1Snippet"); } - public static int reference2Snippet(A a) { + public static void reference2Snippet(A a) { if (a instanceof B) { - return 1; + sink1 = 1; } - return 2; + sink2 = 2; } - public static int test2Snippet(A a) { + public static void test2Snippet(A a) { if (a instanceof B) { B newVal = (B) a; if (newVal != null) { - return 1; + sink1 = 1; } } - return 2; + sink2 = 2; } @Test @@ -89,65 +92,104 @@ public class ConditionalEliminationTest5 extends ConditionalEliminationTestBase } @SuppressWarnings("unused") - public static int reference3Snippet(Object a, Object b) { + public static void reference3Snippet(Object a, Object b) { if (a instanceof DistinctA) { DistinctA proxyA = (DistinctA) a; if (b instanceof DistinctB) { - return 1; + sink1 = 1; } } - return 2; + sink2 = 2; } @SuppressWarnings("all") - public static int test3Snippet(Object a, Object b) { + public static void test3Snippet(Object a, Object b) { if (a instanceof DistinctA) { DistinctA proxyA = (DistinctA) a; if (b instanceof DistinctB) { if (proxyA == b) { - return 42; + sink0 = 42; } - return 1; + sink1 = 1; } } - return 2; + sink2 = 2; } @Test public void test3() { - testConditionalElimination("test3Snippet", "reference3Snippet", true); + testConditionalElimination("test3Snippet", "reference3Snippet", true, false); } - public static int reference4Snippet(Object a) { + public static void reference4Snippet(Object a) { if (!(a instanceof B)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } - return 1; + sink1 = 1; } - public static int test4Snippet1(Object a) { + public static void test4Snippet1(Object a) { if (!(a instanceof B)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if (!(a instanceof A)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } - return 1; + sink1 = 1; } - public static int test4Snippet2(Object a) { + public static void test4Snippet2(Object a) { if (!(a instanceof A)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } if (!(a instanceof B)) { - GraalDirectives.deoptimize(); + GraalDirectives.deoptimizeAndInvalidate(); } - return 1; + sink1 = 1; + } + + @SuppressWarnings({"cast", "unused"}) + public static void test4Snippet3(Object a) { + Object pi = (A) a; + if (!(a instanceof B)) { + GraalDirectives.deoptimizeAndInvalidate(); + } + sink1 = 1; + } + + public static void test4Snippet4(Object a) { + if (!(a instanceof A)) { + GraalDirectives.deoptimizeAndInvalidate(); + } + if (!(((A) a) instanceof B)) { + GraalDirectives.deoptimizeAndInvalidate(); + } + sink1 = 1; + } + + @SuppressWarnings({"cast"}) + public static void test4Snippet5(Object a) { + Object pi = (A) a; + if (pi == null) { + GraalDirectives.deoptimizeAndInvalidate(); + } + if (!(a instanceof B)) { + GraalDirectives.deoptimizeAndInvalidate(); + } + sink1 = 1; } @Test public void test4() { testConditionalElimination("test4Snippet1", "reference4Snippet"); testConditionalElimination("test4Snippet2", "reference4Snippet"); + testConditionalElimination("test4Snippet3", "reference4Snippet"); + testConditionalElimination("test4Snippet5", "reference4Snippet"); + } + + @Ignore + @Test + public void test5() { + testConditionalElimination("test4Snippet4", "reference4Snippet", false, true); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest6.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest6.java index 761736079e3..f4e770dad12 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest6.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest6.java @@ -25,9 +25,8 @@ package org.graalvm.compiler.core.test; import org.junit.Test; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest6 extends ConditionalEliminationTestBase { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest7.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest7.java index a6f69e3cdff..6ce50851790 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest7.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest7.java @@ -22,13 +22,14 @@ */ package org.graalvm.compiler.core.test; +import org.junit.Ignore; import org.junit.Test; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ +@Ignore public class ConditionalEliminationTest7 extends ConditionalEliminationTestBase { @SuppressWarnings("all") diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest8.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest8.java index 52498110e4e..1a86b66c1e0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest8.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest8.java @@ -25,9 +25,8 @@ package org.graalvm.compiler.core.test; import org.junit.Test; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest8 extends ConditionalEliminationTestBase { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest9.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest9.java index 2ac03bffd73..558ac83028c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest9.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTest9.java @@ -27,9 +27,8 @@ import org.junit.Test; import org.graalvm.compiler.api.directives.GraalDirectives; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTest9 extends ConditionalEliminationTestBase { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java index 32c8f5f4644..0140fe6e5de 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationTestBase.java @@ -22,83 +22,75 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; -import org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase; import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; /** - * Collection of tests for - * {@link org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase} including those - * that triggered bugs in this phase. + * Collection of tests for {@link org.graalvm.compiler.phases.common.ConditionalEliminationPhase} + * including those that triggered bugs in this phase. */ public class ConditionalEliminationTestBase extends GraalCompilerTest { - - private final boolean disableSimplification; - - protected ConditionalEliminationTestBase() { - disableSimplification = true; - } - - protected ConditionalEliminationTestBase(boolean disableSimplification) { - this.disableSimplification = disableSimplification; - } + protected static int sink0; + protected static int sink1; + protected static int sink2; protected void testConditionalElimination(String snippet, String referenceSnippet) { - testConditionalElimination(snippet, referenceSnippet, false); + testConditionalElimination(snippet, referenceSnippet, false, false); } @SuppressWarnings("try") - protected void testConditionalElimination(String snippet, String referenceSnippet, boolean applyConditionalEliminationOnReference) { + protected void testConditionalElimination(String snippet, String referenceSnippet, boolean applyConditionalEliminationOnReference, boolean applyLowering) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); PhaseContext context = new PhaseContext(getProviders()); CanonicalizerPhase canonicalizer1 = new CanonicalizerPhase(); - if (disableSimplification) { - /** - * Some tests break if simplification is done so only do it when needed. - */ - canonicalizer1.disableSimplification(); - } CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - try (Debug.Scope scope = Debug.scope("ConditionalEliminationTest", graph)) { - canonicalizer1.apply(graph, context); - new ConvertDeoptimizeToGuardPhase().apply(graph, context); - // new DominatorConditionalEliminationPhase(true).apply(graph, context); + try (DebugContext.Scope scope = debug.scope("ConditionalEliminationTest", graph)) { + prepareGraph(graph, canonicalizer1, context, applyLowering); new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, context); canonicalizer.apply(graph, context); canonicalizer.apply(graph, context); new ConvertDeoptimizeToGuardPhase().apply(graph, context); } catch (Throwable t) { - Debug.handle(t); + debug.handle(t); } StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.YES); - try (Debug.Scope scope = Debug.scope("ConditionalEliminationTest.ReferenceGraph", referenceGraph)) { - - new ConvertDeoptimizeToGuardPhase().apply(referenceGraph, context); + try (DebugContext.Scope scope = debug.scope("ConditionalEliminationTest.ReferenceGraph", referenceGraph)) { + prepareGraph(referenceGraph, canonicalizer, context, applyLowering); if (applyConditionalEliminationOnReference) { - new DominatorConditionalEliminationPhase(true).apply(referenceGraph, context); - canonicalizer.apply(referenceGraph, context); - canonicalizer.apply(referenceGraph, context); - } else { - canonicalizer.apply(referenceGraph, context); + new ConditionalEliminationPhase(true).apply(referenceGraph, context); } + canonicalizer.apply(referenceGraph, context); + canonicalizer.apply(referenceGraph, context); + new ConvertDeoptimizeToGuardPhase().apply(graph, context); } catch (Throwable t) { - Debug.handle(t); + debug.handle(t); } assertEquals(referenceGraph, graph); } + protected void prepareGraph(StructuredGraph graph, CanonicalizerPhase canonicalizer, PhaseContext context, boolean applyLowering) { + if (applyLowering) { + new ConvertDeoptimizeToGuardPhase().apply(graph, context); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + canonicalizer.apply(graph, context); + } + canonicalizer.apply(graph, context); + new ConvertDeoptimizeToGuardPhase().apply(graph, context); + } + public void testProxies(String snippet, int expectedProxiesCreated) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); PhaseContext context = new PhaseContext(getProviders()); @@ -110,9 +102,9 @@ public class ConditionalEliminationTestBase extends GraalCompilerTest { canonicalizer.apply(graph, context); int baseProxyCount = graph.getNodes().filter(ProxyNode.class).count(); - new DominatorConditionalEliminationPhase(true).apply(graph, context); + new ConditionalEliminationPhase(true).apply(graph, context); canonicalizer.apply(graph, context); - new SchedulePhase().apply(graph, context); + new SchedulePhase(graph.getOptions()).apply(graph, context); int actualProxiesCreated = graph.getNodes().filter(ProxyNode.class).count() - baseProxyCount; Assert.assertEquals(expectedProxiesCreated, actualProxiesCreated); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CooperativePhaseTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CooperativePhaseTest.java index c5e2ecbb57c..5a8f6418b37 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CooperativePhaseTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CooperativePhaseTest.java @@ -22,16 +22,16 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; +import static org.graalvm.compiler.core.common.util.CompilationAlarm.Options.CompilationExpirationPeriod; -import org.graalvm.compiler.common.RetryableBailoutException; +import org.graalvm.compiler.core.common.RetryableBailoutException; import org.graalvm.compiler.core.common.util.CompilationAlarm; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.Phase; +import org.junit.Test; public class CooperativePhaseTest extends GraalCompilerTest { @@ -43,9 +43,10 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Override protected void run(StructuredGraph graph) { + CompilationAlarm compilationAlarm = CompilationAlarm.current(); while (true) { sleep(200); - if (CompilationAlarm.hasExpired()) { + if (compilationAlarm.hasExpired()) { return; } } @@ -57,9 +58,10 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Override protected void run(StructuredGraph graph) { + CompilationAlarm compilationAlarm = CompilationAlarm.current(); while (true) { sleep(200); - if (CompilationAlarm.hasExpired()) { + if (compilationAlarm.hasExpired()) { throw new RetryableBailoutException("Expiring..."); } } @@ -67,13 +69,14 @@ public class CooperativePhaseTest extends GraalCompilerTest { } - private static class ParlyCooperativePhase extends Phase { + private static class PartiallyCooperativePhase extends Phase { @Override protected void run(StructuredGraph graph) { + CompilationAlarm compilationAlarm = CompilationAlarm.current(); for (int i = 0; i < 10; i++) { sleep(200); - if (CompilationAlarm.hasExpired()) { + if (compilationAlarm.hasExpired()) { throw new RuntimeException("Phase must not exit in the timeout path"); } } @@ -84,7 +87,8 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Override protected void run(StructuredGraph graph) { - if (CompilationAlarm.hasExpired()) { + CompilationAlarm compilationAlarm = CompilationAlarm.current(); + if (compilationAlarm.hasExpired()) { throw new RuntimeException("Phase must not exit in the timeout path"); } } @@ -101,9 +105,11 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Test(timeout = 60_000) @SuppressWarnings("try") public void test01() { - StructuredGraph g = parseEager("snippet", AllowAssumptions.NO); - try (OverrideScope o = OptionValue.override(CompilationAlarm.Options.CompilationExpirationPeriod, 1/* sec */); - CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod()) { + initializeForTimeout(); + OptionValues initialOptions = getInitialOptions(); + OptionValues options = new OptionValues(initialOptions, CompilationExpirationPeriod, 1/* sec */); + try (CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod(options)) { + StructuredGraph g = parseEager("snippet", AllowAssumptions.NO, options); new CooperativePhase().apply(g); } } @@ -111,9 +117,11 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Test(expected = RetryableBailoutException.class, timeout = 60_000) @SuppressWarnings("try") public void test02() { - StructuredGraph g = parseEager("snippet", AllowAssumptions.NO); - try (OverrideScope o = OptionValue.override(CompilationAlarm.Options.CompilationExpirationPeriod, 1/* sec */); - CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod()) { + initializeForTimeout(); + OptionValues initialOptions = getInitialOptions(); + OptionValues options = new OptionValues(initialOptions, CompilationExpirationPeriod, 1/* sec */); + try (CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod(options)) { + StructuredGraph g = parseEager("snippet", AllowAssumptions.NO, options); new UnCooperativePhase().apply(g); } } @@ -121,17 +129,20 @@ public class CooperativePhaseTest extends GraalCompilerTest { @Test(timeout = 60_000) @SuppressWarnings("try") public void test03() { - StructuredGraph g = parseEager("snippet", AllowAssumptions.NO); + initializeForTimeout(); // 0 disables alarm utility - try (OverrideScope o = OptionValue.override(CompilationAlarm.Options.CompilationExpirationPeriod, 0); - CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod()) { - new ParlyCooperativePhase().apply(g); + OptionValues initialOptions = getInitialOptions(); + OptionValues options = new OptionValues(initialOptions, CompilationExpirationPeriod, 0); + try (CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod(options)) { + StructuredGraph g = parseEager("snippet", AllowAssumptions.NO, options); + new PartiallyCooperativePhase().apply(g); } } @Test(timeout = 60_000) @SuppressWarnings("try") public void test04() { + initializeForTimeout(); StructuredGraph g = parseEager("snippet", AllowAssumptions.NO); new CooperativePhaseWithoutAlarm().apply(g); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java index 7655e3a3fd0..8c1e5733a9d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CountedLoopTest.java @@ -35,9 +35,9 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -242,10 +242,8 @@ public class CountedLoopTest extends GraalCompilerTest { } @Override - protected Plugins getDefaultGraphBuilderPlugins() { - Plugins plugins = super.getDefaultGraphBuilderPlugins(); - Registration r = new Registration(plugins.getInvocationPlugins(), CountedLoopTest.class); - + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { + Registration r = new Registration(invocationPlugins, CountedLoopTest.class); r.register2("get", IVProperty.class, int.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1, ValueNode arg2) { @@ -261,8 +259,7 @@ public class CountedLoopTest extends GraalCompilerTest { } } }); - - return plugins; + super.registerInvocationPlugins(invocationPlugins); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DeMorganCanonicalizationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DeMorganCanonicalizationTest.java new file mode 100644 index 00000000000..b61d3da8ffe --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DeMorganCanonicalizationTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.calc.AndNode; +import org.graalvm.compiler.nodes.calc.NotNode; +import org.graalvm.compiler.nodes.calc.OrNode; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.junit.Assert; +import org.junit.Test; + +public class DeMorganCanonicalizationTest extends GraalCompilerTest { + + public static int or(int a, int b) { + return ~a | ~b; + } + + public static int and(int a, int b) { + return ~a & ~b; + } + + @Test + public void testAnd() { + StructuredGraph g = parseEager("and", AllowAssumptions.NO, getInitialOptions()); + new CanonicalizerPhase().apply(g, getDefaultHighTierContext()); + Assert.assertEquals(1, g.getNodes().filter(OrNode.class).count()); + Assert.assertEquals(1, g.getNodes().filter(NotNode.class).count()); + + testAgainstExpected(g.method(), new Result(and(-1, 17), null), (Object) null, -1, 17); + testAgainstExpected(g.method(), new Result(and(-1, 1), null), (Object) null, -1, 1); + testAgainstExpected(g.method(), new Result(and(-1, -1), null), (Object) null, -1, -1); + testAgainstExpected(g.method(), new Result(and(Integer.MIN_VALUE, Integer.MIN_VALUE), null), (Object) null, Integer.MIN_VALUE, Integer.MIN_VALUE); + } + + @Test + public void testOr() { + StructuredGraph g = parseEager("or", AllowAssumptions.NO, getInitialOptions()); + new CanonicalizerPhase().apply(g, getDefaultHighTierContext()); + Assert.assertEquals(1, g.getNodes().filter(AndNode.class).count()); + Assert.assertEquals(1, g.getNodes().filter(NotNode.class).count()); + + testAgainstExpected(g.method(), new Result(or(-1, 17), null), (Object) null, -1, 17); + testAgainstExpected(g.method(), new Result(or(-1, 1), null), (Object) null, -1, 1); + testAgainstExpected(g.method(), new Result(or(-1, -1), null), (Object) null, -1, -1); + testAgainstExpected(g.method(), new Result(or(Integer.MIN_VALUE, Integer.MIN_VALUE), null), (Object) null, Integer.MIN_VALUE, Integer.MIN_VALUE); + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java index 3ea30c0f6fa..fa7c9d64162 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DegeneratedLoopsTest.java @@ -22,16 +22,14 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Test; /** * In the following tests, the usages of local variable "a" are replaced with the integer constant @@ -81,17 +79,18 @@ public class DegeneratedLoopsTest extends GraalCompilerTest { @SuppressWarnings("try") private void test(final String snippet) { - try (Scope s = Debug.scope("DegeneratedLoopsTest", new DebugDumpScope(snippet))) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("DegeneratedLoopsTest", new DebugDumpScope(snippet))) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); HighTierContext context = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); new CanonicalizerPhase().apply(graph, context); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, referenceGraph, "ReferenceGraph"); + debug.dump(DebugContext.BASIC_LEVEL, referenceGraph, "ReferenceGraph"); assertEquals(referenceGraph, graph); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DirectByteBufferTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DirectByteBufferTest.java new file mode 100644 index 00000000000..f7a9b8ed667 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DirectByteBufferTest.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.Collection; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(Parameterized.class) +public class DirectByteBufferTest extends GraalCompilerTest { + + class Ret { + + byte byteValue = 0; + short shortValue = 0; + int intValue = 0; + long longValue = 0; + float floatValue = 0.0f; + double doubleValue = 0.0d; + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Ret)) { + return false; + } + + Ret other = (Ret) obj; + if (this.byteValue != other.byteValue) { + return false; + } + if (this.shortValue != other.shortValue) { + return false; + } + if (this.intValue != other.intValue) { + return false; + } + if (this.longValue != other.longValue) { + return false; + } + if (Float.floatToRawIntBits(this.floatValue) != Float.floatToRawIntBits(other.floatValue)) { + return false; + } + if (Double.doubleToRawLongBits(this.doubleValue) != Double.doubleToRawLongBits(other.doubleValue)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public String toString() { + return String.format("0x%02x, 0x%04x, 0x%08x, 0x%016x,0x%08x, 0x%016x", byteValue, shortValue, intValue, Float.floatToRawIntBits(floatValue), Double.doubleToRawLongBits(doubleValue)); + } + } + + @Parameters(name = "{0}") + public static Collection data() { + ArrayList ret = new ArrayList<>(); + ret.add(new Object[]{ByteOrder.BIG_ENDIAN}); + ret.add(new Object[]{ByteOrder.LITTLE_ENDIAN}); + return ret; + } + + @Parameter public ByteOrder byteOrder; + + Ret alignedReadSnippet(byte[] arg) { + ByteBuffer buffer = makeDirect(arg, byteOrder); + + Ret ret = new Ret(); + ret.byteValue = buffer.get(); + ret.byteValue += buffer.get(); + ret.shortValue = buffer.getShort(); + ret.intValue = buffer.getInt(); + ret.longValue = buffer.getLong(); + ret.doubleValue = buffer.getDouble(); + ret.floatValue = buffer.getFloat(); + + return ret; + } + + @Test + public void testReadAligned() { + byte[] input = new byte[28]; + for (int i = 0; i < 28; i++) { + input[i] = (byte) (7 * (i + 42)); + } + test("alignedReadSnippet", input); + } + + byte[] alignedWriteSnippet(byte a, byte b, short c, int d, long e, double f, float g) { + byte[] ret = new byte[28]; + ByteBuffer buffer = makeDirect(28, byteOrder); + + buffer.put(a); + buffer.put(b); + buffer.putShort(c); + buffer.putInt(d); + buffer.putLong(e); + buffer.putDouble(f); + buffer.putFloat(g); + + buffer.position(0); + buffer.get(ret); + + return ret; + } + + @Test + public void testWriteAligned() { + test("alignedWriteSnippet", (byte) 5, (byte) -3, (short) 17, 42, 0x3FC30A25644B7130L, 84.72, 1.23f); + } + + Ret unalignedReadSnippet(byte[] arg) { + ByteBuffer buffer = makeDirect(arg, byteOrder); + + Ret ret = new Ret(); + ret.byteValue = buffer.get(); + ret.shortValue = buffer.getShort(); + ret.intValue = buffer.getInt(); + ret.longValue = buffer.getLong(); + ret.doubleValue = buffer.getDouble(); + ret.floatValue = buffer.getFloat(); + + return ret; + } + + @Test + public void testReadUnaligned() { + byte[] input = new byte[27]; + for (int i = 0; i < 27; i++) { + input[i] = (byte) (7 * (i + 42)); + } + test("unalignedReadSnippet", input); + } + + byte[] unalignedWriteSnippet(byte a, short b, int c, long d, double e, float f) { + byte[] ret = new byte[27]; + ByteBuffer buffer = makeDirect(27, byteOrder); + + buffer.put(a); + buffer.putShort(b); + buffer.putInt(c); + buffer.putLong(d); + buffer.putDouble(e); + buffer.putFloat(f); + + buffer.position(0); + buffer.get(ret); + + return ret; + } + + @Test + public void testWriteUnaligned() { + test("unalignedWriteSnippet", (byte) -3, (short) 17, 42, 0x3FC30A25644B7130L, 84.72, 1.23f); + } + + private static ByteBuffer makeDirect(byte[] bytes, ByteOrder byteOrder) { + int length = bytes.length; + ByteBuffer buffer = ByteBuffer.allocateDirect(length).order(byteOrder); + buffer.put(bytes); + buffer.position(0); + return buffer; + } + + private static ByteBuffer makeDirect(int length, ByteOrder byteOrder) { + ByteBuffer buffer = ByteBuffer.allocateDirect(length).order(byteOrder); + buffer.position(0); + return buffer; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DontReuseArgumentSpaceTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DontReuseArgumentSpaceTest.java index 776497efd65..63b1820f4cf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DontReuseArgumentSpaceTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DontReuseArgumentSpaceTest.java @@ -28,10 +28,10 @@ import org.junit.Test; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.phases.HighTier; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.Suites; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -40,10 +40,8 @@ public final class DontReuseArgumentSpaceTest extends GraalCompilerTest { @Override @SuppressWarnings("try") - protected Suites createSuites() { - try (OverrideScope scope = OptionValue.override(HighTier.Options.Inline, false)) { - return super.createSuites(); - } + protected Suites createSuites(OptionValues options) { + return super.createSuites(new OptionValues(options, HighTier.Options.Inline, false)); } @BytecodeParserNeverInline @@ -75,7 +73,8 @@ public final class DontReuseArgumentSpaceTest extends GraalCompilerTest { ResolvedJavaMethod javaMethod = getResolvedJavaMethod("killArguments"); StructuredGraph graph = parseEager(javaMethod, AllowAssumptions.YES); CompilationResult compilationResult = compile(javaMethod, graph); - getBackend().createDefaultInstalledCode(javaMethod, compilationResult); + DebugContext debug = getDebugContext(); + getBackend().createDefaultInstalledCode(debug, javaMethod, compilationResult); test("callTwice", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java index 80df81dca8d..fb06a104201 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/EnumSwitchTest.java @@ -27,6 +27,7 @@ import org.junit.Test; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.phases.tiers.Suites; @@ -137,8 +138,8 @@ public class EnumSwitchTest extends GraalCompilerTest { } @Override - protected Suites createSuites() { - Suites ret = super.createSuites(); + protected Suites createSuites(OptionValues options) { + Suites ret = super.createSuites(options); ret.getHighTier().prependPhase(new Phase() { @Override protected void run(StructuredGraph graph) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java index bd5c99f6897..e6e802ce4c1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FinalizableSubclassTest.java @@ -22,34 +22,31 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; -import static org.graalvm.compiler.nodes.StructuredGraph.NO_PROFILING_INFO; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; import java.util.HashMap; -import jdk.vm.ci.meta.Assumptions; -import jdk.vm.ci.meta.Assumptions.Assumption; -import jdk.vm.ci.meta.Assumptions.LeafType; -import jdk.vm.ci.meta.Assumptions.NoFinalizableSubclass; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.java.RegisterFinalizerNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Assert; +import org.junit.Test; + +import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.Assumptions.Assumption; +import jdk.vm.ci.meta.Assumptions.LeafType; +import jdk.vm.ci.meta.Assumptions.NoFinalizableSubclass; +import jdk.vm.ci.meta.ResolvedJavaMethod; public class FinalizableSubclassTest extends GraalCompilerTest { @@ -74,7 +71,8 @@ public class FinalizableSubclassTest extends GraalCompilerTest { Constructor[] constructors = cl.getConstructors(); Assert.assertTrue(constructors.length == 1); final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(constructors[0]); - StructuredGraph graph = new StructuredGraph(javaMethod, allowAssumptions, NO_PROFILING_INFO, INVALID_COMPILATION_ID); + OptionValues options = getInitialOptions(); + StructuredGraph graph = new StructuredGraph.Builder(options, getDebugContext(options), allowAssumptions).method(javaMethod).build(); GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(getDefaultGraphBuilderPlugins()); new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), getProviders().getConstantFieldProvider(), conf, @@ -110,8 +108,9 @@ public class FinalizableSubclassTest extends GraalCompilerTest { */ @Test public void test1() throws ClassNotFoundException { + DebugContext debug = getDebugContext(); for (int i = 0; i < 2; i++) { - ClassTemplateLoader loader = new ClassTemplateLoader(); + ClassTemplateLoader loader = new ClassTemplateLoader(debug); checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), true, AllowAssumptions.NO); checkForRegisterFinalizeNode(loader.findClass("NoFinalizerEverAAAA"), false, AllowAssumptions.YES); @@ -129,8 +128,11 @@ public class FinalizableSubclassTest extends GraalCompilerTest { private final String replaceTo; private HashMap> cache = new HashMap<>(); - ClassTemplateLoader() { + private final DebugContext debug; + + ClassTemplateLoader(DebugContext debug) { loaderInstance++; + this.debug = debug; replaceTo = String.format("%04d", loaderInstance); } @@ -158,14 +160,15 @@ public class FinalizableSubclassTest extends GraalCompilerTest { } catch (IOException e) { Assert.fail("can't access class: " + name); } - dumpStringsInByteArray(classData); + + dumpStringsInByteArray(debug, classData); // replace all occurrences of "AAAA" in classfile int index = -1; while ((index = indexOfAAAA(classData, index + 1)) != -1) { replaceAAAA(classData, index, replaceTo); } - dumpStringsInByteArray(classData); + dumpStringsInByteArray(debug, classData); Class c = defineClass(null, classData, 0, classData.length); cache.put(nameReplaced, c); @@ -195,14 +198,14 @@ public class FinalizableSubclassTest extends GraalCompilerTest { } } - private static void dumpStringsInByteArray(byte[] b) { + private static void dumpStringsInByteArray(DebugContext debug, byte[] b) { boolean wasChar = true; StringBuilder sb = new StringBuilder(); for (Byte x : b) { // check for [a-zA-Z0-9] if ((x >= 0x41 && x <= 0x7a) || (x >= 0x30 && x <= 0x39)) { if (!wasChar) { - Debug.log(sb + ""); + debug.log(sb + ""); sb.setLength(0); } sb.append(String.format("%c", x)); @@ -211,7 +214,7 @@ public class FinalizableSubclassTest extends GraalCompilerTest { wasChar = false; } } - Debug.log(sb + ""); + debug.log(sb + ""); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueDefaultMethodTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueDefaultMethodTest.java index 97851bf052a..42bfc789272 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueDefaultMethodTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueDefaultMethodTest.java @@ -22,18 +22,16 @@ */ package org.graalvm.compiler.core.test; -import jdk.vm.ci.meta.Assumptions.AssumptionResult; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; - -import org.junit.Ignore; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.junit.Ignore; +import org.junit.Test; + +import jdk.vm.ci.meta.Assumptions.AssumptionResult; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; /** * This test illustrates problems and limitations with class hierarchy analysis when default methods @@ -139,13 +137,14 @@ public class FindUniqueDefaultMethodTest extends GraalCompilerTest { @SuppressWarnings("try") protected StructuredGraph buildGraph(final String snippet) { - try (Scope s = Debug.scope("InstanceOfTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { - StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("InstanceOfTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug); compile(graph.method(), graph); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet); + debug.dump(DebugContext.BASIC_LEVEL, graph, snippet); return graph; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java index e75aac37bad..d69e7ea4697 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FloatingReadTest.java @@ -22,11 +22,7 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ReturnNode; @@ -39,6 +35,8 @@ import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Test; public class FloatingReadTest extends GraphScheduleTest { @@ -63,7 +61,8 @@ public class FloatingReadTest extends GraphScheduleTest { @SuppressWarnings("try") private void test(final String snippet) { - try (Scope s = Debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); PhaseContext context = new PhaseContext(getProviders()); @@ -82,7 +81,7 @@ public class FloatingReadTest extends GraphScheduleTest { } } - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After lowering"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After lowering"); Assert.assertNotNull(returnNode); Assert.assertNotNull(monitorexit); @@ -92,7 +91,7 @@ public class FloatingReadTest extends GraphScheduleTest { assertOrderedAfterSchedule(graph, read, (Node) monitorexit); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerAssumptionsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerAssumptionsTest.java index 88fa5d8738d..64a919e014d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerAssumptionsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerAssumptionsTest.java @@ -65,7 +65,7 @@ public abstract class GraalCompilerAssumptionsTest extends GraalCompilerTest { checkGraph(expectedAssumption, graph); CompilationResult compilationResult = compile(javaMethod, graph); - final InstalledCode installedCode = getBackend().createDefaultInstalledCode(javaMethod, compilationResult); + final InstalledCode installedCode = getBackend().createDefaultInstalledCode(graph.getDebug(), javaMethod, compilationResult); assertTrue(installedCode.isValid()); if (classToLoad != null) { String fullName = getClass().getName() + "$" + classToLoad; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java index 9332f698b5d..2f5b0d27dde 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation; +import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI; import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_NO_EXCEPTION; import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION; @@ -31,10 +31,13 @@ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.EnumMap; import java.util.HashMap; @@ -44,24 +47,20 @@ import java.util.Map; import java.util.Set; import java.util.function.Supplier; -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.internal.AssumptionViolatedException; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.core.CompilationPrinter; import org.graalvm.compiler.core.GraalCompiler; import org.graalvm.compiler.core.GraalCompiler.Request; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugDumpHandler; import org.graalvm.compiler.debug.DebugDumpScope; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.Node; @@ -76,16 +75,19 @@ import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.BreakpointNode; +import org.graalvm.compiler.nodes.Cancellable; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.FullInfopointNode; import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.InvokeWithExceptionNode; +import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.ProxyNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.StructuredGraph.Builder; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.cfg.Block; @@ -95,10 +97,11 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.nodes.java.AccessFieldNode; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; -import org.graalvm.compiler.options.DerivedOptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.Phase; @@ -108,16 +111,26 @@ import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.graalvm.compiler.test.AddExports; import org.graalvm.compiler.test.GraalTest; +import org.graalvm.compiler.test.JLModule; +import org.junit.After; +import org.junit.Assert; +import org.junit.Test; +import org.junit.internal.AssumptionViolatedException; import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.Assumptions.Assumption; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaKind; @@ -133,7 +146,7 @@ import jdk.vm.ci.meta.SpeculationLog; *

    * White box tests for Graal compiler transformations use this pattern: *

      - *
    1. Create a graph by {@linkplain #parseEager(String, AllowAssumptions) parsing} a method.
    2. + *
    3. Create a graph by {@linkplain #parseEager parsing} a method.
    4. *
    5. Manually modify the graph (e.g. replace a parameter node with a constant).
    6. *
    7. Apply a transformation to the graph.
    8. *
    9. Assert that the transformed graph is equal to an expected graph.
    10. @@ -147,12 +160,36 @@ import jdk.vm.ci.meta.SpeculationLog; *

      * These tests will be run by the {@code mx unittest} command. */ +@AddExports({"java.base/jdk.internal.org.objectweb.asm", "java.base/jdk.internal.org.objectweb.asm.tree"}) public abstract class GraalCompilerTest extends GraalTest { + /** + * Gets the initial option values provided by the Graal runtime. These are option values + * typically parsed from the command line. + */ + public static OptionValues getInitialOptions() { + return Graal.getRequiredCapability(OptionValues.class); + } + + private static final int BAILOUT_RETRY_LIMIT = 1; private final Providers providers; private final Backend backend; - private final DerivedOptionValue suites; - private final DerivedOptionValue lirSuites; + + /** + * Representative class for the {@code java.base} module. + */ + public static final Class JAVA_BASE = Class.class; + + /** + * Exports the package named {@code packageName} declared in {@code moduleMember}'s module to + * this object's module. This must be called before accessing packages that are no longer public + * as of JDK 9. + */ + protected final void exportPackage(Class moduleMember, String packageName) { + if (!Java8OrEarlier) { + JLModule.exportPackageTo(moduleMember, packageName, getClass()); + } + } /** * Denotes a test method that must be inlined by the {@link BytecodeParser}. @@ -212,8 +249,8 @@ public abstract class GraalCompilerTest extends GraalTest { protected static void shouldBeOptimizedAway() { } - protected Suites createSuites() { - Suites ret = backend.getSuites().getDefaultSuites().copy(); + protected Suites createSuites(OptionValues opts) { + Suites ret = backend.getSuites().getDefaultSuites(opts).copy(); ListIterator> iter = ret.getHighTier().findPhase(ConvertDeoptimizeToGuardPhase.class, true); if (iter == null) { /* @@ -293,16 +330,14 @@ public abstract class GraalCompilerTest extends GraalTest { return ret; } - protected LIRSuites createLIRSuites() { - LIRSuites ret = backend.getSuites().getDefaultLIRSuites().copy(); + protected LIRSuites createLIRSuites(OptionValues opts) { + LIRSuites ret = backend.getSuites().getDefaultLIRSuites(opts).copy(); return ret; } public GraalCompilerTest() { this.backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); this.providers = getBackend().getProviders(); - this.suites = new DerivedOptionValue<>(this::createSuites); - this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites); } /** @@ -321,8 +356,6 @@ public abstract class GraalCompilerTest extends GraalTest { this.backend = runtime.getHostBackend(); } this.providers = backend.getProviders(); - this.suites = new DerivedOptionValue<>(this::createSuites); - this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites); } /** @@ -333,24 +366,35 @@ public abstract class GraalCompilerTest extends GraalTest { public GraalCompilerTest(Backend backend) { this.backend = backend; this.providers = backend.getProviders(); - this.suites = new DerivedOptionValue<>(this::createSuites); - this.lirSuites = new DerivedOptionValue<>(this::createLIRSuites); - } - - private Scope debugScope; - - @Before - public void beforeTest() { - assert debugScope == null; - debugScope = Debug.scope(getClass()); } + @Override @After public void afterTest() { - if (debugScope != null) { - debugScope.close(); + if (invocationPluginExtensions != null) { + synchronized (this) { + if (invocationPluginExtensions != null) { + extendedInvocationPlugins.removeTestPlugins(invocationPluginExtensions); + extendedInvocationPlugins = null; + invocationPluginExtensions = null; + } + } } - debugScope = null; + super.afterTest(); + } + + /** + * Gets a {@link DebugContext} object corresponding to {@code options}, creating a new one if + * none currently exists. Debug contexts created by this method will have their + * {@link DebugDumpHandler}s closed in {@link #afterTest()}. + */ + protected DebugContext getDebugContext() { + return getDebugContext(getInitialOptions()); + } + + @Override + protected Collection getDebugHandlersFactories() { + return Collections.singletonList(new GraalDebugHandlersFactory(getSnippetReflection())); } protected void assertEquals(StructuredGraph expected, StructuredGraph graph) { @@ -377,13 +421,13 @@ public abstract class GraalCompilerTest extends GraalTest { String mismatchString = compareGraphStrings(expected, expectedString, graph, actualString); if (!excludeVirtual && getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "Node count not matching - expected"); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Node count not matching - actual"); + expected.getDebug().dump(DebugContext.BASIC_LEVEL, expected, "Node count not matching - expected"); + graph.getDebug().dump(DebugContext.BASIC_LEVEL, graph, "Node count not matching - actual"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount() + "\n" + mismatchString); } if (!expectedString.equals(actualString)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "mismatching graphs - expected"); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "mismatching graphs - actual"); + expected.getDebug().dump(DebugContext.BASIC_LEVEL, expected, "mismatching graphs - expected"); + graph.getDebug().dump(DebugContext.BASIC_LEVEL, graph, "mismatching graphs - actual"); Assert.fail(mismatchString); } } @@ -449,22 +493,25 @@ public abstract class GraalCompilerTest extends GraalTest { StringBuilder result = new StringBuilder(); for (Block block : scheduleResult.getCFG().getBlocks()) { - result.append("Block " + block + " "); + result.append("Block ").append(block).append(' '); if (block == scheduleResult.getCFG().getStartBlock()) { result.append("* "); } result.append("-> "); for (Block succ : block.getSuccessors()) { - result.append(succ + " "); + result.append(succ).append(' '); } - result.append("\n"); + result.append('\n'); for (Node node : scheduleResult.getBlockToNodesMap().get(block)) { if (node instanceof ValueNode && node.isAlive()) { - if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode || node instanceof FullInfopointNode)) { + if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode || node instanceof FullInfopointNode || node instanceof ParameterNode)) { if (node instanceof ConstantNode) { String name = checkConstants ? node.toString(Verbosity.Name) : node.getClass().getSimpleName(); - String str = name + (excludeVirtual ? "\n" : " (" + filteredUsageCount(node) + ")\n"); - constantsLines.add(str); + if (excludeVirtual) { + constantsLines.add(name); + } else { + constantsLines.add(name + " (" + filteredUsageCount(node) + ")"); + } } else { int id; if (canonicalId.get(node) != null) { @@ -474,8 +521,17 @@ public abstract class GraalCompilerTest extends GraalTest { canonicalId.set(node, id); } String name = node.getClass().getSimpleName(); - String str = " " + id + "|" + name + (excludeVirtual ? "\n" : " (" + filteredUsageCount(node) + ")\n"); - result.append(str); + result.append(" ").append(id).append('|').append(name); + if (node instanceof AccessFieldNode) { + result.append('#'); + result.append(((AccessFieldNode) node).field()); + } + if (!excludeVirtual) { + result.append(" ("); + result.append(filteredUsageCount(node)); + result.append(')'); + } + result.append('\n'); } } } @@ -483,14 +539,14 @@ public abstract class GraalCompilerTest extends GraalTest { } StringBuilder constantsLinesResult = new StringBuilder(); - constantsLinesResult.append(constantsLines.size() + " constants:\n"); + constantsLinesResult.append(constantsLines.size()).append(" constants:\n"); Collections.sort(constantsLines); for (String s : constantsLines) { constantsLinesResult.append(s); - constantsLinesResult.append("\n"); + constantsLinesResult.append('\n'); } - return constantsLines.toString() + result.toString(); + return constantsLinesResult.toString() + result.toString(); } /** @@ -512,15 +568,15 @@ public abstract class GraalCompilerTest extends GraalTest { StringBuilder result = new StringBuilder(); Block[] blocks = scheduleResult.getCFG().getBlocks(); for (Block block : blocks) { - result.append("Block " + block + " "); + result.append("Block ").append(block).append(' '); if (block == scheduleResult.getCFG().getStartBlock()) { result.append("* "); } result.append("-> "); for (Block succ : block.getSuccessors()) { - result.append(succ + " "); + result.append(succ).append(' '); } - result.append("\n"); + result.append('\n'); for (Node node : scheduleResult.getBlockToNodesMap().get(block)) { result.append(String.format("%1S\n", node)); } @@ -532,14 +588,6 @@ public abstract class GraalCompilerTest extends GraalTest { return backend; } - protected Suites getSuites() { - return suites.getValue(); - } - - protected LIRSuites getLIRSuites() { - return lirSuites.getValue(); - } - protected final Providers getProviders() { return providers; } @@ -548,6 +596,10 @@ public abstract class GraalCompilerTest extends GraalTest { return new HighTierContext(getProviders(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL); } + protected MidTierContext getDefaultMidTierContext() { + return new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, null); + } + protected SnippetReflectionProvider getSnippetReflection() { return Graal.getRequiredCapability(SnippetReflectionProvider.class); } @@ -617,11 +669,12 @@ public abstract class GraalCompilerTest extends GraalTest { } } - protected Object referenceInvoke(ResolvedJavaMethod method, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { + protected Object referenceInvoke(ResolvedJavaMethod method, Object receiver, Object... args) + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { return invoke(method, receiver, args); } - protected static class Result { + public static class Result { public final Object returnValue; public final Throwable exception; @@ -665,12 +718,16 @@ public abstract class GraalCompilerTest extends GraalTest { } protected Result executeActual(ResolvedJavaMethod method, Object receiver, Object... args) { + return executeActual(getInitialOptions(), method, receiver, args); + } + + protected Result executeActual(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) { before(method); Object[] executeArgs = argsWithReceiver(receiver, args); checkArgs(method, executeArgs); - InstalledCode compiledMethod = getCode(method); + InstalledCode compiledMethod = getCode(method, options); try { return new Result(compiledMethod.executeVarargs(executeArgs), null); } catch (Throwable e) { @@ -718,14 +775,19 @@ public abstract class GraalCompilerTest extends GraalTest { return applyArgSuppliers(executeArgs); } - protected void test(String name, Object... args) { + protected final Result test(String name, Object... args) { + return test(getInitialOptions(), name, args); + } + + protected final Result test(OptionValues options, String name, Object... args) { try { ResolvedJavaMethod method = getResolvedJavaMethod(name); Object receiver = method.isStatic() ? null : this; - test(method, receiver, args); + return test(options, method, receiver, args); } catch (AssumptionViolatedException e) { // Suppress so that subsequent calls to this method within the // same Junit @Test annotated method can proceed. + return null; } } @@ -745,12 +807,16 @@ public abstract class GraalCompilerTest extends GraalTest { return supplier; } - protected void test(ResolvedJavaMethod method, Object receiver, Object... args) { + protected Result test(ResolvedJavaMethod method, Object receiver, Object... args) { + return test(getInitialOptions(), method, receiver, args); + } + + protected Result test(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) { Result expect = executeExpected(method, receiver, args); - if (getCodeCache() == null) { - return; + if (getCodeCache() != null) { + testAgainstExpected(options, method, expect, receiver, args); } - testAgainstExpected(method, expect, receiver, args); + return expect; } /** @@ -770,17 +836,30 @@ public abstract class GraalCompilerTest extends GraalTest { return res; } - protected void testAgainstExpected(ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { - testAgainstExpected(method, expect, Collections. emptySet(), receiver, args); + protected final void testAgainstExpected(ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { + testAgainstExpected(getInitialOptions(), method, expect, Collections. emptySet(), receiver, args); } - protected Result executeActualCheckDeopt(ResolvedJavaMethod method, Set shouldNotDeopt, Object receiver, Object... args) { + protected void testAgainstExpected(ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { + testAgainstExpected(getInitialOptions(), method, expect, shouldNotDeopt, receiver, args); + } + + protected final void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { + testAgainstExpected(options, method, expect, Collections. emptySet(), receiver, args); + } + + protected void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { + Result actual = executeActualCheckDeopt(options, method, shouldNotDeopt, receiver, args); + assertEquals(expect, actual); + } + + protected Result executeActualCheckDeopt(OptionValues options, ResolvedJavaMethod method, Set shouldNotDeopt, Object receiver, Object... args) { Map deoptCounts = new EnumMap<>(DeoptimizationReason.class); ProfilingInfo profile = method.getProfilingInfo(); for (DeoptimizationReason reason : shouldNotDeopt) { deoptCounts.put(reason, profile.getDeoptimizationCount(reason)); } - Result actual = executeActual(method, receiver, args); + Result actual = executeActual(options, method, receiver, args); profile = method.getProfilingInfo(); // profile can change after execution for (DeoptimizationReason reason : shouldNotDeopt) { Assert.assertEquals((int) deoptCounts.get(reason), profile.getDeoptimizationCount(reason)); @@ -801,19 +880,18 @@ public abstract class GraalCompilerTest extends GraalTest { } } - protected void testAgainstExpected(ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { - Result actual = executeActualCheckDeopt(method, shouldNotDeopt, receiver, args); - assertEquals(expect, actual); - } - private Map cache = new HashMap<>(); /** * Gets installed code for a given method, compiling it first if necessary. The graph is parsed - * {@link #parseEager(ResolvedJavaMethod, AllowAssumptions) eagerly}. + * {@link #parseEager eagerly}. */ - protected InstalledCode getCode(ResolvedJavaMethod method) { - return getCode(method, null); + protected final InstalledCode getCode(ResolvedJavaMethod method) { + return getCode(method, null, false, false, getInitialOptions()); + } + + protected final InstalledCode getCode(ResolvedJavaMethod method, OptionValues options) { + return getCode(method, null, false, false, options); } /** @@ -823,12 +901,8 @@ public abstract class GraalCompilerTest extends GraalTest { * @param graph the graph to be compiled. If null, a graph will be obtained from * {@code installedCodeOwner} via {@link #parseForCompile(ResolvedJavaMethod)}. */ - protected InstalledCode getCode(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph) { - return getCode(installedCodeOwner, graph, false); - } - - protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph0, boolean forceCompile) { - return getCode(installedCodeOwner, graph0, forceCompile, false); + protected final InstalledCode getCode(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph) { + return getCode(installedCodeOwner, graph, false, false, graph == null ? getInitialOptions() : graph.getOptions()); } /** @@ -839,11 +913,25 @@ public abstract class GraalCompilerTest extends GraalTest { * {@code installedCodeOwner} via {@link #parseForCompile(ResolvedJavaMethod)}. * @param forceCompile specifies whether to ignore any previous code cached for the (method, * key) pair - * @param installDefault specifies whether to install as the default implementation + */ + protected final InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile) { + return getCode(installedCodeOwner, graph, forceCompile, false, graph == null ? getInitialOptions() : graph.getOptions()); + } + + /** + * Gets installed code for a given method and graph, compiling it first if necessary. + * + * @param installedCodeOwner the method the compiled code will be associated with when installed + * @param graph the graph to be compiled. If null, a graph will be obtained from + * {@code installedCodeOwner} via {@link #parseForCompile(ResolvedJavaMethod)}. + * @param forceCompile specifies whether to ignore any previous code cached for the (method, + * key) pair + * @param installAsDefault specifies whether to install as the default implementation + * @param options the options that will be used in {@link #parseForCompile(ResolvedJavaMethod)} */ @SuppressWarnings("try") - protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile, boolean installDefault) { - if (!forceCompile) { + protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { + if (!forceCompile && graph == null) { InstalledCode cached = cache.get(installedCodeOwner); if (cached != null) { if (cached.isValid()) { @@ -851,41 +939,51 @@ public abstract class GraalCompilerTest extends GraalTest { } } } + // loop for retrying compilation + for (int retry = 0; retry <= BAILOUT_RETRY_LIMIT; retry++) { + final CompilationIdentifier id = getOrCreateCompilationId(installedCodeOwner, graph); - final CompilationIdentifier id = getOrCreateCompilationId(installedCodeOwner, graph); + InstalledCode installedCode = null; + StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, id, options) : graph; + DebugContext debug = graphToCompile.getDebug(); - InstalledCode installedCode = null; - try (AllocSpy spy = AllocSpy.open(installedCodeOwner); Scope ds = Debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) { - final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed(); - if (printCompilation) { - TTY.println(String.format("@%-6s Graal %-70s %-45s %-50s ...", id, installedCodeOwner.getDeclaringClass().getName(), installedCodeOwner.getName(), installedCodeOwner.getSignature())); - } - long start = System.currentTimeMillis(); - CompilationResult compResult = compile(installedCodeOwner, graph, id); - if (printCompilation) { - TTY.println(String.format("@%-6s Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize())); - } + try (AllocSpy spy = AllocSpy.open(installedCodeOwner); DebugContext.Scope ds = debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) { + CompilationPrinter printer = CompilationPrinter.begin(options, id, installedCodeOwner, INVOCATION_ENTRY_BCI); + CompilationResult compResult = compile(installedCodeOwner, graphToCompile, new CompilationResult(), id, options); + printer.finish(compResult); - try (Scope s = Debug.scope("CodeInstall", getCodeCache(), installedCodeOwner, compResult)) { - if (installDefault) { - installedCode = addDefaultMethod(installedCodeOwner, compResult); - } else { - installedCode = addMethod(installedCodeOwner, compResult); - } - if (installedCode == null) { - throw new GraalError("Could not install code for " + installedCodeOwner.format("%H.%n(%p)")); + try (DebugContext.Scope s = debug.scope("CodeInstall", getCodeCache(), installedCodeOwner, compResult); + DebugContext.Activation a = debug.activate()) { + try { + if (installAsDefault) { + installedCode = addDefaultMethod(debug, installedCodeOwner, compResult); + } else { + installedCode = addMethod(debug, installedCodeOwner, compResult); + } + if (installedCode == null) { + throw new GraalError("Could not install code for " + installedCodeOwner.format("%H.%n(%p)")); + } + } catch (BailoutException e) { + if (retry <= BAILOUT_RETRY_LIMIT && graph == null && !e.isPermanent()) { + // retry (if there is no predefined graph) + TTY.println(String.format("Restart compilation %s (%s) due to a non-permanent bailout!", installedCodeOwner, id)); + continue; + } + throw e; + } + } catch (Throwable e) { + throw debug.handle(e); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } - } catch (Throwable e) { - throw Debug.handle(e); - } - if (!forceCompile) { - cache.put(installedCodeOwner, installedCode); + if (!forceCompile) { + cache.put(installedCodeOwner, installedCode); + } + return installedCode; } - return installedCode; + throw GraalError.shouldNotReachHere(); } /** @@ -893,15 +991,22 @@ public abstract class GraalCompilerTest extends GraalTest { * {@link #compile(ResolvedJavaMethod, StructuredGraph)} if the second parameter to that method * is null. * - * The default implementation in {@link GraalCompilerTest} is to call - * {@link #parseEager(ResolvedJavaMethod, AllowAssumptions)}. + * The default implementation in {@link GraalCompilerTest} is to call {@link #parseEager}. */ - protected final StructuredGraph parseForCompile(ResolvedJavaMethod method) { - return parseEager(method, AllowAssumptions.YES); + protected StructuredGraph parseForCompile(ResolvedJavaMethod method, OptionValues options) { + return parseEager(method, AllowAssumptions.YES, getCompilationId(method), options); } - protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId) { - return parseEager(method, AllowAssumptions.YES, compilationId); + protected final StructuredGraph parseForCompile(ResolvedJavaMethod method, DebugContext debug) { + return parseEager(method, AllowAssumptions.YES, debug); + } + + protected final StructuredGraph parseForCompile(ResolvedJavaMethod method) { + return parseEager(method, AllowAssumptions.YES, getCompilationId(method), getInitialOptions()); + } + + protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId, OptionValues options) { + return parseEager(method, AllowAssumptions.YES, compilationId, options); } /** @@ -913,11 +1018,18 @@ public abstract class GraalCompilerTest extends GraalTest { * {@link #parseForCompile(ResolvedJavaMethod)}. */ protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph) { - return compile(installedCodeOwner, graph, getOrCreateCompilationId(installedCodeOwner, graph)); + OptionValues options = graph == null ? getInitialOptions() : graph.getOptions(); + return compile(installedCodeOwner, graph, new CompilationResult(), getOrCreateCompilationId(installedCodeOwner, graph), options); } - protected CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationIdentifier compilationId) { - return compile(installedCodeOwner, graph, new CompilationResult(), compilationId); + protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationIdentifier compilationId) { + OptionValues options = graph == null ? getInitialOptions() : graph.getOptions(); + return compile(installedCodeOwner, graph, new CompilationResult(), compilationId, options); + } + + protected final CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, OptionValues options) { + assert graph == null || graph.getOptions() == options; + return compile(installedCodeOwner, graph, new CompilationResult(), getOrCreateCompilationId(installedCodeOwner, graph), options); } /** @@ -927,19 +1039,20 @@ public abstract class GraalCompilerTest extends GraalTest { * @param graph the graph to be compiled for {@code installedCodeOwner}. If null, a graph will * be obtained from {@code installedCodeOwner} via * {@link #parseForCompile(ResolvedJavaMethod)}. - * @param compilationResult * @param compilationId */ @SuppressWarnings("try") - protected CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationResult compilationResult, CompilationIdentifier compilationId) { - StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, compilationId) : graph; + protected CompilationResult compile(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, CompilationResult compilationResult, CompilationIdentifier compilationId, OptionValues options) { + StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, compilationId, options) : graph; lastCompiledGraph = graphToCompile; - try (Scope s = Debug.scope("Compile", graphToCompile)) { + DebugContext debug = graphToCompile.getDebug(); + try (DebugContext.Scope s = debug.scope("Compile", graphToCompile)) { + assert options != null; Request request = new Request<>(graphToCompile, installedCodeOwner, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, - graphToCompile.getProfilingInfo(), getSuites(), getLIRSuites(), compilationResult, CompilationResultBuilderFactory.Default); + graphToCompile.getProfilingInfo(), createSuites(options), createLIRSuites(options), compilationResult, CompilationResultBuilderFactory.Default); return GraalCompiler.compile(request); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } @@ -949,20 +1062,20 @@ public abstract class GraalCompilerTest extends GraalTest { return null; } - protected InstalledCode addMethod(final ResolvedJavaMethod method, final CompilationResult compilationResult) { - return backend.addInstalledCode(method, null, compilationResult); + protected InstalledCode addMethod(DebugContext debug, final ResolvedJavaMethod method, final CompilationResult compilationResult) { + return backend.addInstalledCode(debug, method, null, compilationResult); } - protected InstalledCode addDefaultMethod(final ResolvedJavaMethod method, final CompilationResult compilationResult) { - return backend.createDefaultInstalledCode(method, compilationResult); + protected InstalledCode addDefaultMethod(DebugContext debug, final ResolvedJavaMethod method, final CompilationResult compilationResult) { + return backend.createDefaultInstalledCode(debug, method, compilationResult); } - private final Map methodMap = new HashMap<>(); + private final Map methodMap = new HashMap<>(); /** * Converts a reflection {@link Method} to a {@link ResolvedJavaMethod}. */ - protected ResolvedJavaMethod asResolvedJavaMethod(Method method) { + protected ResolvedJavaMethod asResolvedJavaMethod(Executable method) { ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(method); methodMap.put(javaMethod, method); return javaMethod; @@ -984,17 +1097,21 @@ public abstract class GraalCompilerTest extends GraalTest { * Gets the reflection {@link Method} from which a given {@link ResolvedJavaMethod} was created * or null if {@code javaMethod} does not correspond to a reflection method. */ - protected Method lookupMethod(ResolvedJavaMethod javaMethod) { + protected Executable lookupMethod(ResolvedJavaMethod javaMethod) { return methodMap.get(javaMethod); } - protected Object invoke(ResolvedJavaMethod javaMethod, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - Method method = lookupMethod(javaMethod); + protected Object invoke(ResolvedJavaMethod javaMethod, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { + Executable method = lookupMethod(javaMethod); Assert.assertTrue(method != null); if (!method.isAccessible()) { method.setAccessible(true); } - return method.invoke(receiver, applyArgSuppliers(args)); + if (method instanceof Method) { + return ((Method) method).invoke(receiver, applyArgSuppliers(args)); + } + assert receiver == null : "no receiver for constructor invokes"; + return ((Constructor) method).newInstance(applyArgSuppliers(args)); } /** @@ -1002,21 +1119,22 @@ public abstract class GraalCompilerTest extends GraalTest { * produce a graph. * * @param methodName the name of the method in {@code this.getClass()} to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ - protected StructuredGraph parseProfiled(String methodName, AllowAssumptions allowAssumptions) { - return parseProfiled(getResolvedJavaMethod(methodName), allowAssumptions); + protected final StructuredGraph parseProfiled(String methodName, AllowAssumptions allowAssumptions) { + ResolvedJavaMethod method = getResolvedJavaMethod(methodName); + return parse(builder(method, allowAssumptions), getDefaultGraphBuilderSuite()); } /** * Parses a Java method in {@linkplain GraphBuilderConfiguration#getDefault default} mode to * produce a graph. + * + * @param method the method to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ - protected final StructuredGraph parseProfiled(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { - return parseProfiled(m, allowAssumptions, getCompilationId(m)); - } - - protected StructuredGraph parseProfiled(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - return parse1(m, getDefaultGraphBuilderSuite(), allowAssumptions, compilationId); + protected final StructuredGraph parseProfiled(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { + return parse(builder(method, allowAssumptions), getDefaultGraphBuilderSuite()); } /** @@ -1024,47 +1142,124 @@ public abstract class GraalCompilerTest extends GraalTest { * set to true to produce a graph. * * @param methodName the name of the method in {@code this.getClass()} to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ protected final StructuredGraph parseEager(String methodName, AllowAssumptions allowAssumptions) { - return parseEager(getResolvedJavaMethod(methodName), allowAssumptions); + ResolvedJavaMethod method = getResolvedJavaMethod(methodName); + return parse(builder(method, allowAssumptions), getEagerGraphBuilderSuite()); } /** * Parses a Java method with {@linkplain GraphBuilderConfiguration#withEagerResolving(boolean)} * set to true to produce a graph. + * + * @param methodName the name of the method in {@code this.getClass()} to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph + * @param options the option values to be used when compiling the graph */ - protected final StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { - return parseEager(m, allowAssumptions, getCompilationId(m)); + protected final StructuredGraph parseEager(String methodName, AllowAssumptions allowAssumptions, OptionValues options) { + ResolvedJavaMethod method = getResolvedJavaMethod(methodName); + return parse(builder(method, allowAssumptions, options), getEagerGraphBuilderSuite()); } - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withEagerResolving(true)), allowAssumptions, compilationId); + protected final StructuredGraph parseEager(String methodName, AllowAssumptions allowAssumptions, DebugContext debug) { + ResolvedJavaMethod method = getResolvedJavaMethod(methodName); + return parse(builder(method, allowAssumptions, debug), getEagerGraphBuilderSuite()); } /** - * Parses a Java method using {@linkplain GraphBuilderConfiguration#withFullInfopoints(boolean) - * full debug} set to true to produce a graph. + * Parses a Java method with {@linkplain GraphBuilderConfiguration#withEagerResolving(boolean)} + * set to true to produce a graph. + * + * @param method the method to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph */ - protected final StructuredGraph parseDebug(ResolvedJavaMethod m, AllowAssumptions allowAssumptions) { - return parseDebug(m, allowAssumptions, getCompilationId(m)); + protected final StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { + return parse(builder(method, allowAssumptions), getEagerGraphBuilderSuite()); } - protected StructuredGraph parseDebug(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - return parse1(m, getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)), allowAssumptions, compilationId); + protected final StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, DebugContext debug) { + return parse(builder(method, allowAssumptions, debug), getEagerGraphBuilderSuite()); + } + + /** + * Parses a Java method with {@linkplain GraphBuilderConfiguration#withEagerResolving(boolean)} + * set to true to produce a graph. + * + * @param method the method to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph + * @param options the option values to be used when compiling the graph + */ + protected final StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, OptionValues options) { + return parse(builder(method, allowAssumptions, options), getEagerGraphBuilderSuite()); + } + + /** + * Parses a Java method with {@linkplain GraphBuilderConfiguration#withEagerResolving(boolean)} + * set to true to produce a graph. + * + * @param method the method to be parsed + * @param allowAssumptions specifies if {@link Assumption}s can be made compiling the graph + * @param compilationId the compilation identifier to be associated with the graph + * @param options the option values to be used when compiling the graph + */ + protected final StructuredGraph parseEager(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { + return parse(builder(method, allowAssumptions, compilationId, options), getEagerGraphBuilderSuite()); + } + + protected final Builder builder(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, DebugContext debug) { + OptionValues options = debug.getOptions(); + return new Builder(options, debug, allowAssumptions).method(method).compilationId(getCompilationId(method)); + } + + protected final Builder builder(ResolvedJavaMethod method, AllowAssumptions allowAssumptions) { + OptionValues options = getInitialOptions(); + return new Builder(options, getDebugContext(options), allowAssumptions).method(method).compilationId(getCompilationId(method)); + } + + protected final Builder builder(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId, OptionValues options) { + return new Builder(options, getDebugContext(options), allowAssumptions).method(method).compilationId(compilationId); + } + + protected final Builder builder(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, OptionValues options) { + return new Builder(options, getDebugContext(options), allowAssumptions).method(method).compilationId(getCompilationId(method)); + } + + protected PhaseSuite getDebugGraphBuilderSuite() { + return getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)); } @SuppressWarnings("try") - private StructuredGraph parse1(ResolvedJavaMethod javaMethod, PhaseSuite graphBuilderSuite, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { + protected StructuredGraph parse(StructuredGraph.Builder builder, PhaseSuite graphBuilderSuite) { + ResolvedJavaMethod javaMethod = builder.getMethod(); + if (builder.getCancellable() == null) { + builder.cancellable(getCancellable(javaMethod)); + } assert javaMethod.getAnnotation(Test.class) == null : "shouldn't parse method with @Test annotation: " + javaMethod; - StructuredGraph graph = new StructuredGraph(javaMethod, allowAssumptions, getSpeculationLog(), compilationId); - try (Scope ds = Debug.scope("Parsing", javaMethod, graph)) { + StructuredGraph graph = builder.build(); + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope ds = debug.scope("Parsing", javaMethod, graph)) { graphBuilderSuite.apply(graph, getDefaultHighTierContext()); return graph; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } + protected PhaseSuite getEagerGraphBuilderSuite() { + return getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withEagerResolving(true)); + } + + /** + * Gets the cancellable that should be associated with a graph being created by any of the + * {@code parse...()} methods. + * + * @param method the method being parsed into a graph + */ + protected Cancellable getCancellable(ResolvedJavaMethod method) { + return null; + } + protected Plugins getDefaultGraphBuilderPlugins() { PhaseSuite suite = backend.getSuites().getDefaultGraphBuilderSuite(); Plugins defaultPlugins = ((GraphBuilderPhase) suite.findPhase(GraphBuilderPhase.class).previous()).getGraphBuilderConfig().getPlugins(); @@ -1077,17 +1272,16 @@ public abstract class GraalCompilerTest extends GraalTest { return backend.getSuites().getDefaultGraphBuilderSuite().copy(); } - protected PhaseSuite getCustomGraphBuilderSuite(GraphBuilderConfiguration gbConf) { - PhaseSuite suite = getDefaultGraphBuilderSuite(); - ListIterator> iterator = suite.findPhase(GraphBuilderPhase.class); - GraphBuilderConfiguration gbConfCopy = editGraphBuilderConfiguration(gbConf.copy()); - iterator.remove(); - iterator.add(new GraphBuilderPhase(gbConfCopy)); - return suite; - } - - protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) { - InvocationPlugins invocationPlugins = conf.getPlugins().getInvocationPlugins(); + /** + * Registers extra invocation plugins for this test. The extra plugins are removed in the + * {@link #afterTest()} method. + * + * Subclasses overriding this method should always call the same method on the super class in + * case it wants to register plugins. + * + * @param invocationPlugins + */ + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { invocationPlugins.register(new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { @@ -1109,7 +1303,41 @@ public abstract class GraalCompilerTest extends GraalTest { return true; } }, GraalCompilerTest.class, "shouldBeOptimizedAway"); + } + /** + * The {@link #testN(int, String, Object...)} method means multiple threads trying to initialize + * this field. + */ + private volatile InvocationPlugins invocationPluginExtensions; + + private InvocationPlugins extendedInvocationPlugins; + + protected PhaseSuite getCustomGraphBuilderSuite(GraphBuilderConfiguration gbConf) { + PhaseSuite suite = getDefaultGraphBuilderSuite(); + ListIterator> iterator = suite.findPhase(GraphBuilderPhase.class); + initializeInvocationPluginExtensions(); + GraphBuilderConfiguration gbConfCopy = editGraphBuilderConfiguration(gbConf.copy()); + iterator.remove(); + iterator.add(new GraphBuilderPhase(gbConfCopy)); + return suite; + } + + private void initializeInvocationPluginExtensions() { + if (invocationPluginExtensions == null) { + synchronized (this) { + if (invocationPluginExtensions == null) { + InvocationPlugins invocationPlugins = new InvocationPlugins(); + registerInvocationPlugins(invocationPlugins); + extendedInvocationPlugins = getReplacements().getGraphBuilderPlugins().getInvocationPlugins(); + extendedInvocationPlugins.addTestPlugins(invocationPlugins, null); + invocationPluginExtensions = invocationPlugins; + } + } + } + } + + protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) { conf.getPlugins().prependInlineInvokePlugin(new InlineInvokePlugin() { @Override @@ -1186,4 +1414,13 @@ public abstract class GraalCompilerTest extends GraalTest { protected boolean isArchitecture(String name) { return name.equals(backend.getTarget().arch.getName()); } + + /** + * This method should be called in "timeout" tests which JUnit runs in a different thread. + */ + public static void initializeForTimeout() { + // timeout tests run in a separate thread which needs the DebugEnvironment to be + // initialized + // DebugEnvironment.ensureInitialized(getInitialOptions()); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalDebugHandlersFactoryTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalDebugHandlersFactoryTest.java new file mode 100644 index 00000000000..723d127618a --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalDebugHandlersFactoryTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Comparator; + +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; +import org.graalvm.compiler.test.AddExports; +import org.junit.Test; + +@AddExports("jdk.internal.vm.compiler/org.graalvm.compiler.printer") +public class GraalDebugHandlersFactoryTest extends GraalCompilerTest { + + @Test + public void createUniqueTest() throws Exception { + Field maxFileNameLengthField = GraalDebugHandlersFactory.class.getDeclaredField("MAX_FILE_NAME_LENGTH"); + maxFileNameLengthField.setAccessible(true); + int maxFileNameLength = maxFileNameLengthField.getInt(null); + Method createUniqueMethod = GraalDebugHandlersFactory.class.getDeclaredMethod("createUnique", Path.class, String.class, String.class, String.class, boolean.class); + createUniqueMethod.setAccessible(true); + Path tmpDir = Files.createTempDirectory(Paths.get("."), "createUniqueTest"); + try { + for (boolean createDirectory : new boolean[]{true, false}) { + for (String ext : new String[]{"", ".bgv", ".graph-strings"}) { + for (int i = 0; i < maxFileNameLength + 5; i++) { + String id = new String(new char[i]).replace('\0', 'i'); + String label = ""; + createUniqueMethod.invoke(null, tmpDir, id, label, ext, createDirectory); + + id = ""; + label = new String(new char[i]).replace('\0', 'l'); + createUniqueMethod.invoke(null, tmpDir, id, label, ext, createDirectory); + } + } + } + } finally { + deleteTree(tmpDir); + } + } + + private static void deleteTree(Path root) throws IOException { + Files.walk(root).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java index 6dd6b2b5b19..7f319c38a80 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphEncoderTest.java @@ -71,7 +71,7 @@ public class GraphEncoderTest extends GraalCompilerTest { encoder.prepare(originalGraph); } encoder.finishPrepare(); - Map startOffsets = new HashMap<>(); + Map startOffsets = new HashMap<>(); for (StructuredGraph originalGraph : originalGraphs) { startOffsets.put(originalGraph, encoder.encode(originalGraph)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java new file mode 100644 index 00000000000..68043b2b6eb --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugOptions; +import org.graalvm.compiler.debug.DebugContext.Scope; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.junit.Assert; +import org.junit.Test; + +public class GraphResetDebugTest extends GraalCompilerTest { + + public static void testSnippet() { + } + + @SuppressWarnings("try") + @Test + public void test1() { + EconomicMap, Object> map = EconomicMap.create(); + // Configure with an option that enables scopes + map.put(DebugOptions.DumpOnError, true); + DebugContext debug = getDebugContext(new OptionValues(map)); + StructuredGraph graph = parseEager("testSnippet", AllowAssumptions.YES, debug); + boolean resetSucceeded = false; + try (Scope scope = debug.scope("some scope")) { + graph.resetDebug(DebugContext.DISABLED); + resetSucceeded = true; + } catch (AssertionError expected) { + } + Assert.assertFalse(resetSucceeded); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardEliminationCornerCasesTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardEliminationCornerCasesTest.java deleted file mode 100644 index ee219719139..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardEliminationCornerCasesTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.test; - -import org.junit.Test; - -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.nodes.AbstractBeginNode; -import org.graalvm.compiler.nodes.BeginNode; -import org.graalvm.compiler.nodes.FixedNode; -import org.graalvm.compiler.nodes.GuardNode; -import org.graalvm.compiler.nodes.LogicNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.java.InstanceOfNode; -import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.nodes.spi.ValueProxy; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; -import org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase; -import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.schedule.SchedulePhase; -import org.graalvm.compiler.phases.tiers.HighTierContext; - -public class GuardEliminationCornerCasesTest extends GraalCompilerTest { - - static class A { - - } - - static class B extends A { - - } - - static class C extends B { - - } - - static class D extends C { - - } - - @SuppressWarnings({"static-method", "unused"}) - private int testMethod(Object a) { - if (a instanceof A) { - if (a instanceof C) { - if (a instanceof B) { - B b = (B) a; - if (b instanceof C) { - return 1; - } else { - GraalDirectives.deoptimizeAndInvalidate(); - } - } - } else { - GraalDirectives.deoptimizeAndInvalidate(); - } - } - return 0; - } - - @Test - public void testFloatingGuards() { - HighTierContext context = getDefaultHighTierContext(); - StructuredGraph graph = parseEager("testMethod", AllowAssumptions.YES); - new ConvertDeoptimizeToGuardPhase().apply(graph, context); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "after parsing"); - - GuardNode myGuardNode = null; - for (Node n : graph.getNodes()) { - if (n instanceof GuardNode) { - GuardNode guardNode = (GuardNode) n; - LogicNode condition = guardNode.getCondition(); - if (condition instanceof InstanceOfNode) { - InstanceOfNode instanceOfNode = (InstanceOfNode) condition; - if (instanceOfNode.getValue() instanceof ValueProxy) { - myGuardNode = guardNode; - break; - } - } - } - } - - AbstractBeginNode myBegin = (AbstractBeginNode) myGuardNode.getAnchor(); - AbstractBeginNode prevBegin = BeginNode.prevBegin((FixedNode) myBegin.predecessor()); - myGuardNode.setAnchor(prevBegin); - - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "after manual modification"); - graph.reverseUsageOrder(); - new DominatorConditionalEliminationPhase(true).apply(graph, context); - new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST).apply(graph); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java index a84872e309b..fd0e6c2e956 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardedIntrinsicTest.java @@ -24,10 +24,6 @@ package org.graalvm.compiler.core.test; import java.util.List; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; - import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ConstantNode; @@ -39,12 +35,15 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.debug.OpaqueNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -111,15 +110,14 @@ public class GuardedIntrinsicTest extends GraalCompilerTest { private StructuredGraph parsedForCompile; @Override - protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId) { - graph = super.parseForCompile(method, compilationId); - parsedForCompile = (StructuredGraph) graph.copy(); + protected StructuredGraph parseForCompile(ResolvedJavaMethod method, CompilationIdentifier compilationId, OptionValues options) { + graph = super.parseForCompile(method, compilationId, options); + parsedForCompile = (StructuredGraph) graph.copy(graph.getDebug()); return graph; } @Override - protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) { - InvocationPlugins invocationPlugins = conf.getPlugins().getInvocationPlugins(); + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { Registration r = new Registration(invocationPlugins, Super.class); r.register1("getAge", Receiver.class, new InvocationPlugin() { @@ -131,7 +129,7 @@ public class GuardedIntrinsicTest extends GraalCompilerTest { return true; } }); - return super.editGraphBuilderConfiguration(conf); + super.registerInvocationPlugins(invocationPlugins); } public static int referenceMakeSuperAge() { @@ -209,7 +207,7 @@ public class GuardedIntrinsicTest extends GraalCompilerTest { @Override public int hashCode() { int result = ((identity == null) ? 0 : identity.hashCode()); - return result + object.hashCode(); + return result + System.identityHashCode(object); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java index eb9b5ce1162..6ee99a34f14 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashCodeTest.java @@ -22,17 +22,18 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.core.phases.HighTier; import org.graalvm.compiler.core.phases.MidTier; import org.graalvm.compiler.nodes.InvokeNode; +import org.graalvm.compiler.nodes.InvokeWithExceptionNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.tiers.MidTierContext; +import org.junit.Assert; +import org.junit.Test; public class HashCodeTest extends GraalCompilerTest { @@ -143,7 +144,9 @@ public class HashCodeTest extends GraalCompilerTest { private void checkForGuardedIntrinsicPattern(String name) { StructuredGraph g = parseForCompile(getResolvedJavaMethod(name)); - Assert.assertEquals(1, g.getNodes().filter(InvokeNode.class).count()); + int invokeNodeCount = g.getNodes().filter(InvokeNode.class).count(); + int invokeWithExceptionNodeCount = g.getNodes().filter(InvokeWithExceptionNode.class).count(); + Assert.assertEquals(1, invokeNodeCount + invokeWithExceptionNodeCount); Assert.assertEquals(1, g.getNodes().filter(LoadHubNode.class).count()); Assert.assertEquals(1, g.getNodes().filter(LoadMethodNode.class).count()); } @@ -151,8 +154,9 @@ public class HashCodeTest extends GraalCompilerTest { @SuppressWarnings("try") private StructuredGraph buildGraphAfterMidTier(String name) { StructuredGraph g = parseForCompile(getResolvedJavaMethod(name)); - new HighTier().apply(g, getDefaultHighTierContext()); - new MidTier().apply(g, new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, g.getProfilingInfo())); + OptionValues options = getInitialOptions(); + new HighTier(options).apply(g, getDefaultHighTierContext()); + new MidTier(options).apply(g, new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, g.getProfilingInfo())); return g; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java index 0cf12a00ffb..742af4d1d27 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IfCanonicalizerTest.java @@ -22,9 +22,7 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FrameState; @@ -38,9 +36,9 @@ import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.GuardLoweringPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.ValueAnchorCleanupPhase; import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; /** * In the following tests, the usages of local variable "a" are replaced with the integer constant @@ -148,7 +146,7 @@ public class IfCanonicalizerTest extends GraalCompilerTest { @Test public void test6() { - testCombinedIf("test6Snippet", 3); + testCombinedIf("test6Snippet", 4); test("test6Snippet", new int[]{0}); } @@ -197,6 +195,33 @@ public class IfCanonicalizerTest extends GraalCompilerTest { return (n < 0) ? 1 : (n >= 1024) ? 1024 : n + 1; } + @Test + public void test10() { + // Exercise NormalizeCompareNode with long values + test("test10Snippet", 0, 1); + } + + public static long test10Snippet(int x, int y) { + return (x < y) ? -1L : ((x == y) ? 0L : 1L); + } + + @Test + public void test11() { + test("test11Snippet", 0, 1); + } + + public static long test11Snippet(int x, int y) { + long normalizeCompare = normalizeCompareLong(x, y); + if (normalizeCompare == 0) { + return 5; + } + return 1; + } + + private static Long normalizeCompareLong(int x, int y) { + return (x < y) ? -1L : ((x == y) ? 0L : 1L); + } + private void testCombinedIf(String snippet, int count) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); PhaseContext context = new PhaseContext(getProviders()); @@ -205,13 +230,13 @@ public class IfCanonicalizerTest extends GraalCompilerTest { MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); new GuardLoweringPhase().apply(graph, midContext); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); - new ValueAnchorCleanupPhase().apply(graph); new CanonicalizerPhase().apply(graph, context); assertDeepEquals(count, graph.getNodes().filter(IfNode.class).count()); } private void test(String snippet) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + DebugContext debug = graph.getDebug(); ParameterNode param = graph.getNodes(ParameterNode.TYPE).iterator().next(); ConstantNode constant = ConstantNode.forInt(0, graph); for (Node n : param.usages().snapshot()) { @@ -219,7 +244,7 @@ public class IfCanonicalizerTest extends GraalCompilerTest { n.replaceFirstInput(param, constant); } } - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); for (FrameState fs : param.usages().filter(FrameState.class).snapshot()) { fs.replaceFirstInput(param, null); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ImplicitNullCheckTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ImplicitNullCheckTest.java index 99966331254..f896ff124bf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ImplicitNullCheckTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ImplicitNullCheckTest.java @@ -22,13 +22,8 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -42,6 +37,9 @@ import org.graalvm.compiler.phases.common.GuardLoweringPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; /** * Tests that the hub access and the null check are folded. @@ -68,8 +66,9 @@ public class ImplicitNullCheckTest extends GraphScheduleTest { @SuppressWarnings("try") private void test(final String snippet) { - try (Scope s = Debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) { - StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("FloatingReadTest", new DebugDumpScope(snippet))) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug); PhaseContext context = new PhaseContext(getProviders()); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); @@ -80,7 +79,7 @@ public class ImplicitNullCheckTest extends GraphScheduleTest { Assert.assertTrue(graph.getNodes().filter(ReadNode.class).first().canNullCheck()); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java index f93a6f7c3f8..284a20c682e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java @@ -25,10 +25,6 @@ package org.graalvm.compiler.core.test; import static org.graalvm.compiler.core.GraalCompiler.compileGraph; import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions; import static org.junit.Assert.assertNotNull; -import jdk.vm.ci.code.site.Call; -import jdk.vm.ci.code.site.Infopoint; -import jdk.vm.ci.code.site.InfopointReason; -import jdk.vm.ci.meta.ResolvedJavaMethod; import org.junit.Test; @@ -42,6 +38,11 @@ import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; +import jdk.vm.ci.code.site.Call; +import jdk.vm.ci.code.site.Infopoint; +import jdk.vm.ci.code.site.InfopointReason; +import jdk.vm.ci.meta.ResolvedJavaMethod; + /** * Test that infopoints in {@link CompilationResult}s have correctly assigned reasons. */ @@ -63,7 +64,7 @@ public class InfopointReasonTest extends GraalCompilerTest { final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); final StructuredGraph graph = parseEager(method, AllowAssumptions.YES); final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, graph.getProfilingInfo(), - getSuites(), getLIRSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); + createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(), CompilationResultBuilderFactory.Default); for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); if (sp instanceof Call) { @@ -75,7 +76,7 @@ public class InfopointReasonTest extends GraalCompilerTest { @Test public void lineInfopoints() { final ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); - final StructuredGraph graph = parseDebug(method, AllowAssumptions.from(OptAssumptions.getValue())); + final StructuredGraph graph = parse(builder(method, AllowAssumptions.ifTrue(OptAssumptions.getValue(getInitialOptions()))), getDebugGraphBuilderSuite()); int graphLineSPs = 0; for (FullInfopointNode ipn : graph.getNodes().filter(FullInfopointNode.class)) { if (ipn.getReason() == InfopointReason.BYTECODE_POSITION) { @@ -84,8 +85,8 @@ public class InfopointReasonTest extends GraalCompilerTest { } assertTrue(graphLineSPs > 0); PhaseSuite graphBuilderSuite = getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)); - final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), graphBuilderSuite, OptimisticOptimizations.ALL, graph.getProfilingInfo(), getSuites(), - getLIRSuites(), new CompilationResult(), CompilationResultBuilderFactory.Default); + final CompilationResult cr = compileGraph(graph, graph.method(), getProviders(), getBackend(), graphBuilderSuite, OptimisticOptimizations.ALL, graph.getProfilingInfo(), + createSuites(graph.getOptions()), createLIRSuites(graph.getOptions()), new CompilationResult(), CompilationResultBuilderFactory.Default); int lineSPs = 0; for (Infopoint sp : cr.getInfopoints()) { assertNotNull(sp.reason); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InstalledCodeInvalidationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InstalledCodeInvalidationTest.java index 7a450de3281..cb6e4e09b58 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InstalledCodeInvalidationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InstalledCodeInvalidationTest.java @@ -22,12 +22,11 @@ */ package org.graalvm.compiler.core.test; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.code.InvalidInstalledCodeException; - +import org.graalvm.compiler.api.directives.GraalDirectives; import org.junit.Test; -import org.graalvm.compiler.api.directives.GraalDirectives; +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.InvalidInstalledCodeException; public class InstalledCodeInvalidationTest extends GraalCompilerTest { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java index 601fc26ad90..801bba69065 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InterfaceMethodHandleTest.java @@ -27,6 +27,7 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.test.ExportingClassLoader; import org.junit.Test; import org.objectweb.asm.ClassWriter; @@ -37,7 +38,7 @@ import org.objectweb.asm.Opcodes; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.ResolvedJavaMethod; -public final class InterfaceMethodHandleTest extends GraalCompilerTest implements Opcodes { +public final class InterfaceMethodHandleTest extends GraalCompilerTest { private static final MethodHandle INTERFACE_HANDLE_M; private static final MethodHandle INTERFACE_HANDLE_M2; @@ -104,12 +105,12 @@ public final class InterfaceMethodHandleTest extends GraalCompilerTest implement } @Override - protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { + protected InstalledCode addMethod(DebugContext debug, ResolvedJavaMethod method, CompilationResult compResult) { if (method.getDeclaringClass().equals(getMetaAccess().lookupJavaType(M2Thrower.class))) { // Make sure M2Thrower.m2 is invoked from normal code - return getBackend().createDefaultInstalledCode(method, compResult); + return getBackend().createDefaultInstalledCode(debug, method, compResult); } - return super.addMethod(method, compResult); + return super.addMethod(debug, method, compResult); } /** @@ -135,58 +136,65 @@ public final class InterfaceMethodHandleTest extends GraalCompilerTest implement private static final String BASENAME = InterfaceMethodHandleTest.class.getName(); private static final String NAME = BASENAME + "_B"; - private AsmLoader loader = new AsmLoader(UnbalancedMonitorsTest.class.getClassLoader()); + private final AsmLoader loader; - /** - * Construct a type which claims to implement {@link I} but with incorrect access on {@link I#m} - * so that an exception must be thrown. - */ - public static byte[] bytesForB() { + public InterfaceMethodHandleTest() { + exportPackage(JAVA_BASE, "jdk.internal.org.objectweb.asm"); + loader = new AsmLoader(UnbalancedMonitorsTest.class.getClassLoader()); + } - ClassWriter cw = new ClassWriter(0); - MethodVisitor mv; - String jvmName = NAME.replace('.', '/'); - cw.visit(52, ACC_SUPER | ACC_PUBLIC, jvmName, null, "java/lang/Object", new String[]{BASENAME.replace('.', '/') + "$I"}); + static class Gen implements Opcodes { + /** + * Construct a type which claims to implement {@link I} but with incorrect access on + * {@link I#m} so that an exception must be thrown. + */ + public static byte[] bytesForB() { - mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mv.visitInsn(RETURN); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 1); - mv.visitEnd(); + ClassWriter cw = new ClassWriter(0); + MethodVisitor mv; + String jvmName = NAME.replace('.', '/'); + cw.visit(52, ACC_SUPER | ACC_PUBLIC, jvmName, null, "java/lang/Object", new String[]{BASENAME.replace('.', '/') + "$I"}); - mv = cw.visitMethod(ACC_PRIVATE, "m", "()I", null, null); - mv.visitCode(); - l0 = new Label(); - mv.visitLabel(l0); - mv.visitInsn(ICONST_0); - mv.visitInsn(IRETURN); - l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 1); - mv.visitEnd(); + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitMaxs(1, 1); + mv.visitEnd(); - cw.visitEnd(); + mv = cw.visitMethod(ACC_PRIVATE, "m", "()I", null, null); + mv.visitCode(); + l0 = new Label(); + mv.visitLabel(l0); + mv.visitInsn(ICONST_0); + mv.visitInsn(IRETURN); + l1 = new Label(); + mv.visitLabel(l1); + mv.visitMaxs(1, 1); + mv.visitEnd(); - mv = cw.visitMethod(ACC_PRIVATE, "m2", "(IIIIIIIIII)I", null, null); - mv.visitCode(); - l0 = new Label(); - mv.visitLabel(l0); - mv.visitInsn(ICONST_0); - mv.visitInsn(IRETURN); - l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 11); - mv.visitEnd(); + cw.visitEnd(); - cw.visitEnd(); + mv = cw.visitMethod(ACC_PRIVATE, "m2", "(IIIIIIIIII)I", null, null); + mv.visitCode(); + l0 = new Label(); + mv.visitLabel(l0); + mv.visitInsn(ICONST_0); + mv.visitInsn(IRETURN); + l1 = new Label(); + mv.visitLabel(l1); + mv.visitMaxs(1, 11); + mv.visitEnd(); - return cw.toByteArray(); + cw.visitEnd(); + + return cw.toByteArray(); + } } public static class AsmLoader extends ExportingClassLoader { @@ -202,7 +210,7 @@ public final class InterfaceMethodHandleTest extends GraalCompilerTest implement if (loaded != null) { return loaded; } - byte[] bytes = bytesForB(); + byte[] bytes = Gen.bytesForB(); return (loaded = defineClass(name, bytes, 0, bytes.length)); } else { return super.findClass(name); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java index 9e0d5a9430b..ac909fc5d1f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LockEliminationTest.java @@ -25,7 +25,8 @@ package org.graalvm.compiler.core.test; import jdk.vm.ci.meta.ResolvedJavaMethod; import org.junit.Test; - +import org.graalvm.compiler.loop.DefaultLoopPolicies; +import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.java.MonitorExitNode; @@ -35,7 +36,6 @@ import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.LockEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.ValueAnchorCleanupPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; @@ -92,6 +92,26 @@ public class LockEliminationTest extends GraalCompilerTest { assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count()); } + public void testUnrolledSyncSnippet(Object a) { + for (int i = 0; i < 3; i++) { + synchronized (a) { + + } + } + } + + @Test + public void testUnrolledSync() { + StructuredGraph graph = getGraph("testUnrolledSyncSnippet"); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + canonicalizer.apply(graph, new PhaseContext(getProviders())); + HighTierContext context = getDefaultHighTierContext(); + new LoopFullUnrollPhase(canonicalizer, new DefaultLoopPolicies()).apply(graph, context); + new LockEliminationPhase().apply(graph); + assertDeepEquals(1, graph.getNodes().filter(RawMonitorEnterNode.class).count()); + assertDeepEquals(1, graph.getNodes().filter(MonitorExitNode.class).count()); + } + private StructuredGraph getGraph(String snippet) { ResolvedJavaMethod method = getResolvedJavaMethod(snippet); StructuredGraph graph = parseEager(method, AllowAssumptions.YES); @@ -101,7 +121,6 @@ public class LockEliminationTest extends GraalCompilerTest { new CanonicalizerPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - new ValueAnchorCleanupPhase().apply(graph); new LockEliminationPhase().apply(graph); return graph; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java index 75c5d71b369..2ad055b27a9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LongNodeChainTest.java @@ -24,18 +24,17 @@ package org.graalvm.compiler.core.test; import jdk.vm.ci.meta.JavaConstant; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - import org.junit.Assert; import org.junit.Test; - +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.debug.OpaqueNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; @@ -55,7 +54,8 @@ public class LongNodeChainTest extends GraalCompilerTest { private void longAddChain(boolean reverse) { HighTierContext context = getDefaultHighTierContext(); - StructuredGraph graph = new StructuredGraph(AllowAssumptions.NO, INVALID_COMPILATION_ID); + OptionValues options = getInitialOptions(); + StructuredGraph graph = new StructuredGraph.Builder(options, DebugContext.create(options, DebugHandlersFactory.LOADER)).build(); ValueNode constant = graph.unique(ConstantNode.forPrimitive(JavaConstant.INT_1)); ValueNode value = null; if (reverse) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopFullUnrollTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopFullUnrollTest.java new file mode 100644 index 00000000000..8b70067a25a --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopFullUnrollTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugDumpScope; +import org.graalvm.compiler.loop.DefaultLoopPolicies; +import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase; +import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; + +public class LoopFullUnrollTest extends GraalCompilerTest { + + public static int testMinToMax(int input) { + int ret = 2; + int current = input; + for (long i = Long.MIN_VALUE; i < Long.MAX_VALUE; i++) { + ret *= 2 + current; + current /= 50; + } + return ret; + } + + @Test + public void runMinToMax() throws Throwable { + test("testMinToMax", 1); + } + + public static int testMinTo0(int input) { + int ret = 2; + int current = input; + for (long i = Long.MIN_VALUE; i <= 0; i++) { + ret *= 2 + current; + current /= 50; + } + return ret; + } + + @Test + public void runMinTo0() throws Throwable { + test("testMinTo0", 1); + } + + public static int testNegativeTripCount(int input) { + int ret = 2; + int current = input; + for (long i = 0; i <= -20; i++) { + ret *= 2 + current; + current /= 50; + } + return ret; + } + + @Test + public void runNegativeTripCount() throws Throwable { + test("testNegativeTripCount", 0); + } + + @SuppressWarnings("try") + private void test(String snippet, int loopCount) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope(getClass().getSimpleName(), new DebugDumpScope(snippet))) { + final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, debug); + + PhaseContext context = new PhaseContext(getProviders()); + new LoopFullUnrollPhase(new CanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context); + + assertTrue(graph.getNodes().filter(LoopBeginNode.class).count() == loopCount); + } catch (Throwable e) { + throw debug.handle(e); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopUnswitchTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopUnswitchTest.java index 3c4e12436b6..9afff3fa8d4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopUnswitchTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/LoopUnswitchTest.java @@ -22,10 +22,7 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.loop.DefaultLoopPolicies; import org.graalvm.compiler.loop.phases.LoopUnswitchingPhase; @@ -33,6 +30,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; public class LoopUnswitchTest extends GraalCompilerTest { @@ -124,6 +122,7 @@ public class LoopUnswitchTest extends GraalCompilerTest { @SuppressWarnings("try") private void test(String snippet, String referenceSnippet) { + DebugContext debug = getDebugContext(); final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); final StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); @@ -135,10 +134,10 @@ public class LoopUnswitchTest extends GraalCompilerTest { new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders())); - try (Scope s = Debug.scope("Test", new DebugDumpScope("Test:" + snippet))) { + try (DebugContext.Scope s = debug.scope("Test", new DebugDumpScope("Test:" + snippet))) { assertEquals(referenceGraph, graph); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryArithmeticTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryArithmeticTest.java index ae12cbfd4dc..e4a74f9b4b0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryArithmeticTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryArithmeticTest.java @@ -28,12 +28,13 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; import org.junit.Test; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; public class MemoryArithmeticTest extends GraalCompilerTest { @Override - protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) { - return getCode(method, graph, true); + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { + return super.getCode(method, graph, true, installAsDefault, options); } /** diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryGraphCanonicalizeTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryGraphCanonicalizeTest.java new file mode 100644 index 00000000000..0cb9a312921 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryGraphCanonicalizeTest.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.memory.WriteNode; +import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.FloatingReadPhase; +import org.graalvm.compiler.phases.common.IncrementalCanonicalizerPhase; +import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Test; + +public class MemoryGraphCanonicalizeTest extends GraalCompilerTest { + static class TestObject { + Object object; + Integer integer; + int value; + volatile boolean written; + } + + public static void simpleElimination(TestObject object) { + object.object = object; + object.value = object.integer; + object.value = object.integer + 2; + object.value = object.integer + 3; + } + + @Test + public void testSimpleElimination() { + testGraph("simpleElimination", 2); + } + + public static void complexElimination(TestObject object) { + object.object = object; + object.value = object.integer; + object.value = object.integer + 2; + if (object.object == null) { + object.value = object.integer + 3; + } else { + object.object = new Object(); + } + object.written = true; + object.value = 5; + } + + @Test + public void testComplexElimination() { + testGraph("complexElimination", 6); + } + + public void testGraph(String name, int expectedWrites) { + StructuredGraph graph = parseEager(name, StructuredGraph.AllowAssumptions.YES); + HighTierContext context = getDefaultHighTierContext(); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + new IncrementalCanonicalizerPhase<>(canonicalizer, new FloatingReadPhase()).apply(graph, context); + new CanonicalizerPhase().apply(graph, context); + int writes = graph.getNodes().filter(WriteNode.class).count(); + assertTrue(writes == expectedWrites, "Expected %d writes, found %d", expectedWrites, writes); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java index 398fc133e0d..3b432740415 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MemoryScheduleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,12 +31,8 @@ import static org.junit.Assert.assertThat; import java.util.ArrayList; import java.util.List; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.nodes.ReturnNode; @@ -48,8 +44,7 @@ import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; @@ -61,6 +56,8 @@ import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.MidTierContext; +import org.junit.Assert; +import org.junit.Test; /** * In these test the FrameStates are explicitly cleared out, so that the scheduling of @@ -89,6 +86,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { private static final Container container = new Container(); private static final List containerList = new ArrayList<>(); + private static final double LOOP_ENTRY_PROBABILITY = 0.9; /** * In this test the read should be scheduled before the write. @@ -165,7 +163,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { try { return container.a; } finally { - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { if (b < 0) { container.b = 10; } else { @@ -190,7 +188,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { try { return container.a; } finally { - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { if (b < 0) { container.b = 10; } else { @@ -213,7 +211,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { */ public static int testLoop3Snippet(int a) { int j = 0; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { if (i - container.a == 0) { break; } @@ -246,7 +244,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { public static int testLoop5Snippet(int a, int b, MemoryScheduleTest obj) { int ret = 0; int bb = b; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { ret = obj.hash; if (a > 10) { bb++; @@ -272,13 +270,13 @@ public class MemoryScheduleTest extends GraphScheduleTest { public static int testLoop6Snippet(int a, int b, MemoryScheduleTest obj) { int ret = 0; int bb = b; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { ret = obj.hash; if (a > 10) { bb++; } else { bb--; - for (int j = 0; j < b; ++j) { + for (int j = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, j < b); ++j) { obj.hash = 3; } } @@ -301,15 +299,15 @@ public class MemoryScheduleTest extends GraphScheduleTest { public static int testLoop7Snippet(int a, int b, MemoryScheduleTest obj) { int ret = 0; int bb = b; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { ret = obj.hash; if (a > 10) { bb++; } else { bb--; - for (int k = 0; k < a; ++k) { + for (int k = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, k < a); ++k) { if (k % 2 == 1) { - for (int j = 0; j < b; ++j) { + for (int j = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, j < b); ++j) { obj.hash = 3; } } @@ -333,12 +331,12 @@ public class MemoryScheduleTest extends GraphScheduleTest { */ public static int testLoop8Snippet(int a, int b) { int result = container.a; - for (int i = 0; i < a; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a); i++) { if (b < 0) { container.b = 10; break; } else { - for (int j = 0; j < b; j++) { + for (int j = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, j < b); j++) { container.a = 0; } } @@ -378,25 +376,6 @@ public class MemoryScheduleTest extends GraphScheduleTest { Assert.assertEquals(0, readBlock.getLoopDepth()); } - /** - * Here the read should float to the end (into the same block as the return). - */ - public static int testArrayCopySnippet(Integer intValue, char[] a, char[] b, int len) { - System.arraycopy(a, 0, b, 0, len); - return intValue.intValue(); - } - - @Test - public void testArrayCopy() { - ScheduleResult schedule = getFinalSchedule("testArrayCopySnippet", TestMode.INLINED_WITHOUT_FRAMESTATES); - StructuredGraph graph = schedule.getCFG().getStartBlock().getBeginNode().graph(); - assertDeepEquals(1, graph.getNodes(ReturnNode.TYPE).count()); - ReturnNode ret = graph.getNodes(ReturnNode.TYPE).first(); - assertTrue(ret.result() + " should be a FloatingReadNode", ret.result() instanceof FloatingReadNode); - assertDeepEquals(schedule.getCFG().blockFor(ret), schedule.getCFG().blockFor(ret.result())); - assertReadWithinAllReturnBlocks(schedule, true); - } - /** * Here the read should not float to the end. */ @@ -644,7 +623,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { public static int testLoop4Snippet(int count) { int[] a = new int[count]; - for (int i = 0; i < a.length; i++) { + for (int i = 0; GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < a.length); i++) { a[i] = i; } @@ -652,7 +631,7 @@ public class MemoryScheduleTest extends GraphScheduleTest { int iwrap = count - 1; int sum = 0; - while (i < count) { + while (GraalDirectives.injectBranchProbability(LOOP_ENTRY_PROBABILITY, i < count)) { sum += (a[i] + a[iwrap]) / 2; iwrap = i; i++; @@ -723,36 +702,36 @@ public class MemoryScheduleTest extends GraphScheduleTest { @SuppressWarnings("try") private ScheduleResult getFinalSchedule(final String snippet, final TestMode mode, final SchedulingStrategy schedulingStrategy) { - final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); - try (Scope d = Debug.scope("FloatingReadTest", graph)) { - try (OverrideScope s = OptionValue.override(OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS, OptImplicitNullChecks, false)) { - HighTierContext context = getDefaultHighTierContext(); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - canonicalizer.apply(graph, context); - if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { - new InliningPhase(canonicalizer).apply(graph, context); - } - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); - if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { - graph.clearAllStateAfter(); - } - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "after removal of framestates"); - - new FloatingReadPhase().apply(graph); - new RemoveValueProxyPhase().apply(graph); - - MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); - new GuardLoweringPhase().apply(graph, midContext); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); - new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER).apply(graph, midContext); - - SchedulePhase schedule = new SchedulePhase(schedulingStrategy); - schedule.apply(graph); - assertDeepEquals(1, graph.getNodes().filter(StartNode.class).count()); - return graph.getLastSchedule(); + OptionValues options = new OptionValues(getInitialOptions(), OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS, OptImplicitNullChecks, false); + final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, options); + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope d = debug.scope("FloatingReadTest", graph)) { + HighTierContext context = getDefaultHighTierContext(); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + canonicalizer.apply(graph, context); + if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { + new InliningPhase(canonicalizer).apply(graph, context); } + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); + if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) { + graph.clearAllStateAfter(); + } + debug.dump(DebugContext.BASIC_LEVEL, graph, "after removal of framestates"); + + new FloatingReadPhase().apply(graph); + new RemoveValueProxyPhase().apply(graph); + + MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); + new GuardLoweringPhase().apply(graph, midContext); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER).apply(graph, midContext); + + SchedulePhase schedule = new SchedulePhase(schedulingStrategy); + schedule.apply(graph); + assertDeepEquals(1, graph.getNodes().filter(StartNode.class).count()); + return graph.getLastSchedule(); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java index 15a682de023..08f83bbe2cf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MergeCanonicalizerTest.java @@ -22,14 +22,13 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; public class MergeCanonicalizerTest extends GraalCompilerTest { @@ -61,7 +60,7 @@ public class MergeCanonicalizerTest extends GraalCompilerTest { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + graph.getDebug().dump(DebugContext.BASIC_LEVEL, graph, "Graph"); assertDeepEquals(returnCount, graph.getNodes(ReturnNode.TYPE).count()); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MethodHandleEagerResolution.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MethodHandleEagerResolution.java index 458227396f4..79e06a498c9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MethodHandleEagerResolution.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MethodHandleEagerResolution.java @@ -31,7 +31,10 @@ import org.junit.Test; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.test.AddExports; +// Export needed to open String.value field to reflection by this test +@AddExports("java.base/java.lang") public final class MethodHandleEagerResolution extends GraalCompilerTest { private static final MethodHandle FIELD_HANDLE; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NarrowingReadTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NarrowingReadTest.java new file mode 100644 index 00000000000..859b9856719 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NarrowingReadTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.junit.Test; + +/** + * Sometimes it's possible to emit a smaller read from a larger memory location instead reading the + * whole thing and truncating it. Make sure it returns the right value. + */ +public class NarrowingReadTest extends GraalCompilerTest { + + public byte testNarrowReadSnippetByte(Long l) { + return (byte) l.longValue(); + } + + @Test + public void testNarrowReadByte() { + test("testNarrowReadSnippetByte", Long.valueOf(Byte.MAX_VALUE)); + } + + public short testNarrowReadSnippetShort(Long l) { + return (short) l.longValue(); + } + + @Test + public void testNarrowReadShort() { + test("testNarrowReadSnippetShort", Long.valueOf(Short.MAX_VALUE)); + } + + public int testNarrowReadSnippetInt(Long l) { + return (int) l.longValue(); + } + + @Test + public void testNarrowReadInt() { + test("testNarrowReadSnippetInt", Long.valueOf(Integer.MAX_VALUE)); + } + + public long testNarrowReadSnippetIntToLong(Long l) { + return (int) l.longValue(); + } + + @Test + public void testNarrowReadIntToLong() { + test("testNarrowReadSnippetIntToLong", Long.valueOf(Integer.MAX_VALUE)); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java index 543bb442408..d1bc6d4f962 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NestedLoopTest.java @@ -22,11 +22,8 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.core.common.cfg.Loop; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; @@ -34,6 +31,8 @@ import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.junit.Assert; +import org.junit.Test; public class NestedLoopTest extends GraalCompilerTest { @@ -142,7 +141,8 @@ public class NestedLoopTest extends GraalCompilerTest { private void test(String snippet, int rootExits, int nestedExits, int innerExits) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); Assert.assertEquals(3, cfg.getLoops().size()); @@ -162,7 +162,7 @@ public class NestedLoopTest extends GraalCompilerTest { Assert.assertEquals(rootExits, rootLoop.getExits().size()); Assert.assertEquals(nestedExits, nestedLoop.getExits().size()); Assert.assertEquals(innerExits, innerMostLoop.getExits().size()); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); } private static boolean contains(Loop loop, Invoke node, ControlFlowGraph cfg) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java index ee5ca6685a8..51fdf9426d3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/NodePropertiesTest.java @@ -22,11 +22,7 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -35,13 +31,14 @@ import org.graalvm.compiler.java.ComputeLoopFrequenciesClosure; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.NodeCostProvider; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase.CustomCanonicalizer; import org.graalvm.compiler.phases.contract.NodeCostUtil; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Test; public class NodePropertiesTest extends GraalCompilerTest { @@ -58,9 +55,11 @@ public class NodePropertiesTest extends GraalCompilerTest { x = 2; sideEffect = null; } + int b = 4; sideEffect = null; + int c = b % 5; // can shift - return a * x * 4; + return a * x * c; } public static int test2Snippet(int a) { @@ -74,7 +73,7 @@ public class NodePropertiesTest extends GraalCompilerTest { } sideEffect = null; // cannot shift - return a * x * 3; + return a * x * 41; } public static final int ITERATIONS_LOOP_1 = 128; @@ -145,9 +144,8 @@ public class NodePropertiesTest extends GraalCompilerTest { } public static int arrayStoreTest(int a) { - String s = String.valueOf(a); - array[2] = s; - return s.length(); + array[2] = a; + return a; } public static int fieldLoad(int a) { @@ -162,10 +160,10 @@ public class NodePropertiesTest extends GraalCompilerTest { @Test public void testCanonicalizationExample() { HighTierContext htc = getDefaultHighTierContext(); - ImprovementSavingCanonicalizer c1 = new ImprovementSavingCanonicalizer(htc.getNodeCostProvider()); + ImprovementSavingCanonicalizer c1 = new ImprovementSavingCanonicalizer(); StructuredGraph g1 = parseForCompile(getResolvedJavaMethod("test1Snippet")); new CanonicalizerPhase(c1).apply(g1, htc); - ImprovementSavingCanonicalizer c2 = new ImprovementSavingCanonicalizer(htc.getNodeCostProvider()); + ImprovementSavingCanonicalizer c2 = new ImprovementSavingCanonicalizer(); StructuredGraph g2 = parseForCompile(getResolvedJavaMethod("test2Snippet")); new CanonicalizerPhase(c2).apply(g2, htc); Assert.assertTrue(c1.savedCycles > c2.savedCycles); @@ -197,7 +195,7 @@ public class NodePropertiesTest extends GraalCompilerTest { GraphCostPhase gc2 = new GraphCostPhase(); gc1.apply(g1, htc); gc2.apply(g2, htc); - Debug.log("Test testDifferentLoopFaster --> 1.Graph cycles:%f size:%f vs. 2.Graph cycles:%f size:%f\n", gc1.finalCycles, gc1.finalSize, gc2.finalCycles, gc2.finalSize); + g1.getDebug().log("Test testDifferentLoopFaster --> 1.Graph cycles:%f size:%f vs. 2.Graph cycles:%f size:%f\n", gc1.finalCycles, gc1.finalSize, gc2.finalCycles, gc2.finalSize); Assert.assertTrue(gc2.finalCycles > gc1.finalCycles); Assert.assertTrue(gc2.finalSize == gc1.finalSize); } @@ -215,7 +213,7 @@ public class NodePropertiesTest extends GraalCompilerTest { GraphCostPhase gc2 = new GraphCostPhase(); gc1.apply(g1, htc); gc2.apply(g2, htc); - Debug.log("Test testSameLoopMoreIterationsCostlier --> 1.Graph cycles:%f size:%f vs. 2.Graph cycles:%f size:%f\n", gc1.finalCycles, gc1.finalSize, gc2.finalCycles, gc2.finalSize); + g1.getDebug().log("Test testSameLoopMoreIterationsCostlier --> 1.Graph cycles:%f size:%f vs. 2.Graph cycles:%f size:%f\n", gc1.finalCycles, gc1.finalSize, gc2.finalCycles, gc2.finalSize); Assert.assertTrue(gc2.finalCycles > gc1.finalCycles); Assert.assertTrue(gc2.finalSize == gc1.finalSize); } @@ -232,7 +230,7 @@ public class NodePropertiesTest extends GraalCompilerTest { GraphCostPhase gc2 = new GraphCostPhase(); gc1.apply(g1, htc); gc2.apply(g2, htc); - Debug.log("Test testDifferentLoopsInnerOuter --> 1.Graph cycles:%f size:%f vs. 2.Graph cycles:%f size:%f\n", gc1.finalCycles, gc1.finalSize, gc2.finalCycles, gc2.finalSize); + g1.getDebug().log("Test testDifferentLoopsInnerOuter --> 1.Graph cycles:%f size:%f vs. 2.Graph cycles:%f size:%f\n", gc1.finalCycles, gc1.finalSize, gc2.finalCycles, gc2.finalSize); Assert.assertTrue(gc2.finalSize > gc1.finalSize); } @@ -247,9 +245,9 @@ public class NodePropertiesTest extends GraalCompilerTest { GraphCostPhase gc2 = new GraphCostPhase(); gc1.apply(g1, htc); gc2.apply(g2, htc); - Debug.log("Test Graph Cost --> 1.Graph cost:%f vs. 2.Graph cost:%f\n", gc1.finalCycles, gc2.finalCycles); + g1.getDebug().log("Test Graph Cost --> 1.Graph cost:%f vs. 2.Graph cost:%f\n", gc1.finalCycles, gc2.finalCycles); Assert.assertTrue(gc2.finalCycles > gc1.finalCycles); - Assert.assertTrue(gc2.finalSize == gc1.finalSize + 1/* mul has 3 const input */); + Assert.assertTrue(gc2.finalSize == gc1.finalSize); } @Test @@ -268,7 +266,7 @@ public class NodePropertiesTest extends GraalCompilerTest { new CanonicalizerPhase().apply(g1, htc); GraphCostPhase gc1 = new GraphCostPhase(); gc1.apply(g1, htc); - Assert.assertEquals(35, gc1.finalCycles, 25); + Assert.assertEquals(15, gc1.finalCycles, 25); } @Test @@ -278,7 +276,7 @@ public class NodePropertiesTest extends GraalCompilerTest { new CanonicalizerPhase().apply(g1, htc); GraphCostPhase gc1 = new GraphCostPhase(); gc1.apply(g1, htc); - Assert.assertEquals(50, gc1.finalCycles, 25); + Assert.assertEquals(15, gc1.finalCycles, 25); } @Test @@ -288,7 +286,7 @@ public class NodePropertiesTest extends GraalCompilerTest { new CanonicalizerPhase().apply(g1, htc); GraphCostPhase gc1 = new GraphCostPhase(); gc1.apply(g1, htc); - Assert.assertEquals(30, gc1.finalCycles, 25); + Assert.assertEquals(15, gc1.finalCycles, 25); } @Test @@ -298,16 +296,11 @@ public class NodePropertiesTest extends GraalCompilerTest { new CanonicalizerPhase().apply(g1, htc); GraphCostPhase gc1 = new GraphCostPhase(); gc1.apply(g1, htc); - Assert.assertEquals(120, gc1.finalCycles, 25); + Assert.assertEquals(15, gc1.finalCycles, 25); } static class ImprovementSavingCanonicalizer extends CustomCanonicalizer { private int savedCycles; - private final NodeCostProvider nodeCostProvider; - - ImprovementSavingCanonicalizer(NodeCostProvider nodeCostProvider) { - this.nodeCostProvider = nodeCostProvider; - } @Override public void simplify(Node node, SimplifierTool tool) { @@ -316,7 +309,7 @@ public class NodePropertiesTest extends GraalCompilerTest { Canonicalizable.Binary bc = (Canonicalizable.Binary) node; Node canonicalized = bc.canonical(tool, bc.getX(), bc.getY()); if (canonicalized != node) { - savedCycles += nodeCostProvider.getEstimatedCPUCycles(node) - nodeCostProvider.getEstimatedCPUCycles(canonicalized); + savedCycles += node.estimatedNodeCycles().value - canonicalized.estimatedNodeCycles().value; } } } @@ -328,8 +321,8 @@ public class NodePropertiesTest extends GraalCompilerTest { @Override protected void run(StructuredGraph graph, PhaseContext context) { - finalCycles = NodeCostUtil.computeGraphCycles(graph, context.getNodeCostProvider(), true); - finalSize = NodeCostUtil.computeGraphSize(graph, context.getNodeCostProvider()); + finalCycles = NodeCostUtil.computeGraphCycles(graph, true); + finalSize = NodeCostUtil.computeGraphSize(graph); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java index ccd10019b0d..a0091273103 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/OptionsVerifierTest.java @@ -41,12 +41,12 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.ServiceLoader; import java.util.Set; import org.graalvm.compiler.options.OptionDescriptor; import org.graalvm.compiler.options.OptionDescriptors; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionsParser; import org.graalvm.compiler.test.GraalTest; import org.junit.Test; import org.objectweb.asm.ClassReader; @@ -57,7 +57,7 @@ import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; /** - * Verifies a class declaring one or more {@linkplain OptionValue options} has a class initializer + * Verifies a class declaring one or more {@linkplain OptionKey options} has a class initializer * that only initializes the option(s). This sanity check mitigates the possibility of an option * value being used before being set. */ @@ -67,7 +67,7 @@ public class OptionsVerifierTest { public void verifyOptions() throws IOException { try (Classpath cp = new Classpath()) { HashSet> checked = new HashSet<>(); - for (OptionDescriptors opts : ServiceLoader.load(OptionDescriptors.class, getClass().getClassLoader())) { + for (OptionDescriptors opts : OptionsParser.getOptionsLoader()) { for (OptionDescriptor desc : opts) { OptionsVerifier.checkClass(desc.getDeclaringClass(), desc, checked, cp); } @@ -257,7 +257,7 @@ public class OptionsVerifierTest { private boolean checkInvokeTarget(Executable method) { Class holder = method.getDeclaringClass(); if (method instanceof Constructor) { - if (OptionValue.class.isAssignableFrom(holder)) { + if (OptionKey.class.isAssignableFrom(holder)) { return true; } } else if (Arrays.asList(boxingTypes).contains(holder)) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PhiCreationTests.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PhiCreationTests.java index b5101a9fcdd..b89a4f18538 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PhiCreationTests.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PhiCreationTests.java @@ -22,13 +22,12 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValuePhiNode; +import org.junit.Assert; +import org.junit.Test; /** * In the following tests, the correct removal of redundant phis during graph building is tested. @@ -70,7 +69,8 @@ public class PhiCreationTests extends GraalCompilerTest { @Test public void test3() { StructuredGraph graph = parseEager("test3Snippet", AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } @@ -86,7 +86,8 @@ public class PhiCreationTests extends GraalCompilerTest { @Test public void test4() { StructuredGraph graph = parseEager("test4Snippet", AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); Assert.assertFalse(graph.getNodes().filter(ValuePhiNode.class).iterator().hasNext()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java index 9cfacabc7b8..0add7f01647 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushNodesThroughPiTest.java @@ -22,14 +22,7 @@ */ package org.graalvm.compiler.core.test; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaType; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.PiNode; @@ -42,8 +35,13 @@ import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.PushThroughPiPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaType; public class PushNodesThroughPiTest extends GraalCompilerTest { @@ -72,11 +70,13 @@ public class PushNodesThroughPiTest extends GraalCompilerTest { return ret; } + @Ignore @Test @SuppressWarnings("try") public void test1() { final String snippet = "test1Snippet"; - try (Scope s = Debug.scope("PushThroughPi", new DebugDumpScope(snippet))) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("PushThroughPi", new DebugDumpScope(snippet))) { StructuredGraph graph = compileTestSnippet(snippet); for (ReadNode rn : graph.getNodes().filter(ReadNode.class)) { OffsetAddressNode address = (OffsetAddressNode) rn.getAddress(); @@ -95,7 +95,7 @@ public class PushNodesThroughPiTest extends GraalCompilerTest { Assert.assertTrue(graph.getNodes().filter(IsNullNode.class).count() == 1); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } @@ -105,7 +105,6 @@ public class PushNodesThroughPiTest extends GraalCompilerTest { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); - new PushThroughPiPhase().apply(graph); canonicalizer.apply(graph, context); return graph; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java index 04cacfacff0..f941f71fc0e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/PushThroughIfTest.java @@ -22,15 +22,14 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; public class PushThroughIfTest extends GraalCompilerTest { @@ -59,7 +58,8 @@ public class PushThroughIfTest extends GraalCompilerTest { private void test(String snippet, String reference) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); for (FrameState fs : graph.getNodes(FrameState.TYPE).snapshot()) { fs.replaceAtUsages(null); GraphUtil.killWithUnusedFloatingInputs(fs); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java index 57ca56a6aae..c492078e006 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReadAfterCheckCastTest.java @@ -22,11 +22,7 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -36,8 +32,9 @@ import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FloatingReadPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.OptimizeGuardAnchorsPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Test; /* consider * B b = (B) a; @@ -85,7 +82,8 @@ public class ReadAfterCheckCastTest extends GraphScheduleTest { @SuppressWarnings("try") private void test(final String snippet) { - try (Scope s = Debug.scope("ReadAfterCheckCastTest", new DebugDumpScope(snippet))) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("ReadAfterCheckCastTest", new DebugDumpScope(snippet))) { // check shape of graph, with lots of assumptions. will probably fail if graph // structure changes significantly StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); @@ -93,10 +91,9 @@ public class ReadAfterCheckCastTest extends GraphScheduleTest { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); new FloatingReadPhase().apply(graph); - new OptimizeGuardAnchorsPhase().apply(graph); canonicalizer.apply(graph, context); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After lowering"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After lowering"); for (FloatingReadNode node : graph.getNodes(ParameterNode.TYPE).first().usages().filter(FloatingReadNode.class)) { // Checking that the parameter a is not directly used for the access to field @@ -104,7 +101,7 @@ public class ReadAfterCheckCastTest extends GraphScheduleTest { Assert.assertTrue(node.getLocationIdentity().isImmutable()); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java index 6596d4d22c5..b4737bfb441 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReentrantBlockIteratorTest.java @@ -242,7 +242,7 @@ public class ReentrantBlockIteratorTest extends GraalCompilerTest { ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, false); ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); // schedule for IGV - new SchedulePhase().apply(graph); + new SchedulePhase(graph.getOptions()).apply(graph); return blocks; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReferenceGetLoopTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReferenceGetLoopTest.java index ff37a85e7ff..22b7b3f7676 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReferenceGetLoopTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReferenceGetLoopTest.java @@ -27,14 +27,13 @@ import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import org.junit.Test; - -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.loop.LoopEx; import org.graalvm.compiler.loop.LoopsData; import org.graalvm.compiler.nodes.FieldLocationIdentity; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.memory.Access; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.ResolvedJavaField; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java new file mode 100644 index 00000000000..3f83a26ce07 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; + +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionDescriptor; +import org.graalvm.compiler.options.OptionDescriptors; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.MapCursor; + +/** + * An implementation of {@link OptionDescriptor} that uses reflection to create descriptors from a + * list of field name and help text pairs. We cannot use the {@link Option} annotation as it has a + * {@link RetentionPolicy#SOURCE} retention policy. + * + * This class is useful for working with {@link OptionKey} and {@link OptionValues} but without + * having to rely on {@link Option} and its associated annotation processor. + */ +public class ReflectionOptionDescriptors implements OptionDescriptors { + + /** + * Extracts name/value entries from a set of properties based on a given name prefix. + * + * @param properties the properties set to extract from + * @param prefix entries whose names start with this prefix are extracted + * @param stripPrefix specifies whether to remove the prefix from the names in the returned map + */ + public static EconomicMap extractEntries(Properties properties, String prefix, boolean stripPrefix) { + EconomicMap matches = EconomicMap.create(); + for (Map.Entry e : properties.entrySet()) { + String name = (String) e.getKey(); + if (name.startsWith(prefix)) { + String value = (String) e.getValue(); + if (stripPrefix) { + name = name.substring(prefix.length()); + } + matches.put(name, value); + } + } + return matches; + } + + private final EconomicMap descriptors = EconomicMap.create(); + + public ReflectionOptionDescriptors(Class declaringClass, String... fieldsAndHelp) { + assert fieldsAndHelp.length % 2 == 0; + for (int i = 0; i < fieldsAndHelp.length; i += 2) { + String fieldName = fieldsAndHelp[i]; + String help = fieldsAndHelp[i + 1]; + addOption(declaringClass, fieldName, help); + } + } + + public ReflectionOptionDescriptors(Class declaringClass, EconomicMap fieldsAndHelp) { + MapCursor cursor = fieldsAndHelp.getEntries(); + while (cursor.advance()) { + String fieldName = cursor.getKey(); + String help = cursor.getValue(); + addOption(declaringClass, fieldName, help); + } + } + + private void addOption(Class declaringClass, String fieldName, String help) { + try { + Field f = declaringClass.getDeclaredField(fieldName); + if (!OptionKey.class.isAssignableFrom(f.getType())) { + throw new IllegalArgumentException(String.format("Option field must be of type %s: %s", OptionKey.class.getName(), f)); + } + if (!Modifier.isStatic(f.getModifiers())) { + throw new IllegalArgumentException(String.format("Option field must be static: %s", f)); + } + f.setAccessible(true); + Type declaredType = f.getAnnotatedType().getType(); + if (!(declaredType instanceof ParameterizedType)) { + throw new IllegalArgumentException(String.format("Option field must have a parameterized type: %s", f)); + } + ParameterizedType pt = (ParameterizedType) declaredType; + Type[] actualTypeArguments = pt.getActualTypeArguments(); + assert actualTypeArguments.length == 1; + Class optionType = (Class) actualTypeArguments[0]; + descriptors.put(fieldName, OptionDescriptor.create(fieldName, optionType, help, declaringClass, fieldName, (OptionKey) f.get(null))); + } catch (IllegalAccessException | NoSuchFieldException e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public Iterator iterator() { + return descriptors.getValues().iterator(); + } + + @Override + public OptionDescriptor get(String value) { + return descriptors.get(value); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java index da59e9c7235..41d27061e6e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ScalarTypeSystemTest.java @@ -22,13 +22,12 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; /** * In the following tests, the scalar type system of the compiler should be complete enough to see @@ -131,7 +130,7 @@ public class ScalarTypeSystemTest extends GraalCompilerTest { private void test(final String snippet, final String referenceSnippet) { // No debug scope to reduce console noise for @Test(expected = ...) tests StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + graph.getDebug().dump(DebugContext.BASIC_LEVEL, graph, "Graph"); PhaseContext context = new PhaseContext(getProviders()); new CanonicalizerPhase().apply(graph, context); StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java index 22cbe45ca72..e9676b52c7e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SchedulingTest2.java @@ -24,10 +24,8 @@ package org.graalvm.compiler.core.test; import java.util.List; -import org.junit.Test; - import org.graalvm.compiler.core.common.cfg.BlockMap; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.nodes.BeginNode; @@ -51,6 +49,7 @@ import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; public class SchedulingTest2 extends GraphScheduleTest { @@ -65,11 +64,12 @@ public class SchedulingTest2 extends GraphScheduleTest { @Test public void testValueProxyInputs() { StructuredGraph graph = parseEager("testSnippet", AllowAssumptions.YES); + DebugContext debug = graph.getDebug(); ReturnNode returnNode = graph.getNodes(ReturnNode.TYPE).first(); BeginNode beginNode = graph.add(new BeginNode()); returnNode.replaceAtPredecessor(beginNode); beginNode.setNext(returnNode); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST); schedulePhase.apply(graph); ScheduleResult schedule = graph.getLastSchedule(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java index f750ecd1d49..940628abc58 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SimpleCFGTest.java @@ -22,12 +22,7 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractMergeNode; import org.graalvm.compiler.nodes.BeginNode; @@ -39,16 +34,23 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; +import org.junit.Assert; +import org.junit.Test; public class SimpleCFGTest extends GraalCompilerTest { private static void dumpGraph(final StructuredGraph graph) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); } @Test public void testImplies() { - StructuredGraph graph = new StructuredGraph(AllowAssumptions.YES, INVALID_COMPILATION_ID); + OptionValues options = getInitialOptions(); + DebugContext debug = DebugContext.create(options, new GraalDebugHandlersFactory(getSnippetReflection())); + StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).build(); EndNode trueEnd = graph.add(new EndNode()); EndNode falseEnd = graph.add(new EndNode()); @@ -109,7 +111,13 @@ public class SimpleCFGTest extends GraalCompilerTest { } public static void assertDominatedSize(Block block, int size) { - Assert.assertEquals("number of dominated blocks of " + block, size, block.getDominated().size()); + int count = 0; + Block domChild = block.getFirstDominated(); + while (domChild != null) { + count++; + domChild = domChild.getDominatedSibling(); + } + Assert.assertEquals("number of dominated blocks of " + block, size, count); } public static void assertPostdominator(Block block, Block expectedPostdominator) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampMemoryAccessTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampMemoryAccessTest.java new file mode 100644 index 00000000000..5cbd3a3434b --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampMemoryAccessTest.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.core.common.type.StampFactory; +import org.junit.Ignore; +import org.junit.Test; + +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MemoryAccessProvider; + +/** + * + */ +public class StampMemoryAccessTest extends GraalCompilerTest { + + @Ignore("not all JVMCI versions are safe yet") + @Test + public void testReadPrimitive() { + MemoryAccessProvider memory = getConstantReflection().getMemoryAccessProvider(); + JavaConstant base = getSnippetReflection().forObject(""); + Stamp stamp = StampFactory.forKind(JavaKind.Long); + assertTrue(stamp.readConstant(memory, base, 128) == null); + } + + @Ignore("not all JVMCI versions are safe yet") + @Test + public void testReadObject() { + MemoryAccessProvider memory = getConstantReflection().getMemoryAccessProvider(); + JavaConstant base = getSnippetReflection().forObject(""); + Stamp stamp = StampFactory.forKind(JavaKind.Object); + assertTrue(stamp.readConstant(memory, base, 128) == null); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java index 27af889f90a..866b2f8328a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StaticInterfaceFieldTest.java @@ -22,27 +22,20 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; -import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.INTERCEPT; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.lang.reflect.Method; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import org.junit.Assume; -import org.junit.Test; - import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; -import org.graalvm.compiler.debug.DelegatingDebugConfig; +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.VerifyPhase; @@ -50,6 +43,11 @@ import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.runtime.RuntimeProvider; import org.graalvm.compiler.test.GraalTest; +import org.junit.Assume; +import org.junit.Test; + +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Test that interfaces are correctly initialized by a static field resolution during eager graph @@ -92,11 +90,13 @@ public class StaticInterfaceFieldTest extends GraalTest { final Method m = getMethod(clazz, methodName); ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); - try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); Debug.Scope ds = Debug.scope("GraphBuilding", graph, method)) { + OptionValues options = getInitialOptions(); + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build(); + try (DebugCloseable s = debug.disableIntercept(); DebugContext.Scope ds = debug.scope("GraphBuilding", graph, method)) { graphBuilderSuite.apply(graph, context); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java index 6c9dd26fcb8..c11955198bb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StraighteningTest.java @@ -22,13 +22,12 @@ */ package org.graalvm.compiler.core.test; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; public class StraighteningTest extends GraalCompilerTest { @@ -88,7 +87,8 @@ public class StraighteningTest extends GraalCompilerTest { private void test(final String snippet) { // No debug scope to reduce console noise for @Test(expected = ...) tests StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); StructuredGraph referenceGraph = parseEager(REFERENCE_SNIPPET, AllowAssumptions.YES); assertEquals(referenceGraph, graph); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java index 2dc0a53fe30..c3bb56844a5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeSystemTest.java @@ -28,11 +28,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodeinfo.Verbosity; @@ -44,9 +40,12 @@ import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.DominatorConditionalEliminationPhase; +import org.graalvm.compiler.phases.common.ConditionalEliminationPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; /** * In the following tests, the scalar type system of the compiler should be complete enough to see @@ -180,18 +179,19 @@ public class TypeSystemTest extends GraalCompilerTest { private void test(String snippet, String referenceSnippet) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); /* * When using FlowSensitiveReductionPhase instead of ConditionalEliminationPhase, * tail-duplication gets activated thus resulting in a graph with more nodes than the * reference graph. */ - new DominatorConditionalEliminationPhase(false).apply(graph, new PhaseContext(getProviders())); + new ConditionalEliminationPhase(false).apply(graph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); // a second canonicalizer is needed to process nested MaterializeNodes new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); StructuredGraph referenceGraph = parseEager(referenceSnippet, AllowAssumptions.NO); - new DominatorConditionalEliminationPhase(false).apply(referenceGraph, new PhaseContext(getProviders())); + new ConditionalEliminationPhase(false).apply(referenceGraph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(referenceGraph, new PhaseContext(getProviders())); assertEquals(referenceGraph, graph); @@ -199,16 +199,17 @@ public class TypeSystemTest extends GraalCompilerTest { @Override protected void assertEquals(StructuredGraph expected, StructuredGraph graph) { + DebugContext debug = graph.getDebug(); if (getNodeCountExcludingUnusedConstants(expected) != getNodeCountExcludingUnusedConstants(graph)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, expected, "expected (node count)"); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "graph (node count)"); + debug.dump(DebugContext.BASIC_LEVEL, expected, "expected (node count)"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "graph (node count)"); Assert.fail("Graphs do not have the same number of nodes: " + expected.getNodeCount() + " vs. " + graph.getNodeCount()); } } public static void outputGraph(StructuredGraph graph, String message) { TTY.println("========================= " + message); - SchedulePhase schedulePhase = new SchedulePhase(); + SchedulePhase schedulePhase = new SchedulePhase(graph.getOptions()); schedulePhase.apply(graph); ScheduleResult schedule = graph.getLastSchedule(); for (Block block : schedule.getCFG().getBlocks()) { @@ -244,7 +245,8 @@ public class TypeSystemTest extends GraalCompilerTest { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph " + snippet); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph " + snippet); Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext()); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java index e6e6249aff8..6b44e9c7a97 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/TypeWriterTest.java @@ -123,7 +123,7 @@ public class TypeWriterTest extends GraalCompilerTest { UnsafeArrayTypeWriter writer = UnsafeArrayTypeWriter.create(supportsUnalignedMemoryAccess); putValues(writer); - byte[] array = new byte[(int) writer.getBytesWritten()]; + byte[] array = new byte[TypeConversion.asU4(writer.getBytesWritten())]; writer.toArray(array); UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(array, 0, supportsUnalignedMemoryAccess); checkValues(reader); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java index 633441b981d..a5762cd4f0a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnbalancedMonitorsTest.java @@ -22,24 +22,21 @@ */ package org.graalvm.compiler.core.test; -import jdk.vm.ci.code.BailoutException; -import jdk.vm.ci.meta.ResolvedJavaMethod; +import org.graalvm.compiler.java.GraphBuilderPhase; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.OptimisticOptimizations; +import org.junit.Test; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - -import org.junit.Test; - -import org.graalvm.compiler.java.GraphBuilderPhase; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.phases.OptimisticOptimizations; +import jdk.vm.ci.code.BailoutException; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Exercise handling of unbalanced monitor operations by the parser. Algorithmically Graal assumes @@ -49,12 +46,16 @@ import org.graalvm.compiler.phases.OptimisticOptimizations; * handle this directly is simplifying for targets of Graal since they don't have to provide a data * flow that checks this property. */ -public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes { +public class UnbalancedMonitorsTest extends GraalCompilerTest { private static final String CLASS_NAME = UnbalancedMonitorsTest.class.getName(); private static final String INNER_CLASS_NAME = CLASS_NAME + "$UnbalancedMonitors"; private static final String CLASS_NAME_INTERNAL = CLASS_NAME.replace('.', '/'); private static final String INNER_CLASS_NAME_INTERNAL = INNER_CLASS_NAME.replace('.', '/'); + public UnbalancedMonitorsTest() { + exportPackage(JAVA_BASE, "jdk.internal.org.objectweb.asm"); + } + private static AsmLoader LOADER = new AsmLoader(UnbalancedMonitorsTest.class.getClassLoader()); @Test @@ -85,7 +86,8 @@ public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes private void checkForBailout(String name) throws ClassNotFoundException { ResolvedJavaMethod method = getResolvedJavaMethod(LOADER.findClass(INNER_CLASS_NAME), name); try { - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + OptionValues options = getInitialOptions(); + StructuredGraph graph = new StructuredGraph.Builder(options, getDebugContext(options)).method(method).build(); Plugins plugins = new Plugins(new InvocationPlugins()); GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true); OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE; @@ -101,6 +103,8 @@ public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes assertTrue("should have bailed out", false); } + static class Gen implements Opcodes { + // @formatter:off // Template class used with Bytecode Outline to generate ASM code // public static class UnbalancedMonitors { @@ -134,165 +138,167 @@ public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes // } // @formatter:on - public static byte[] generateClass() { + public static byte[] generateClass() { - ClassWriter cw = new ClassWriter(0); + ClassWriter cw = new ClassWriter(0); - cw.visit(52, ACC_SUPER | ACC_PUBLIC, INNER_CLASS_NAME_INTERNAL, null, "java/lang/Object", null); + cw.visit(52, ACC_SUPER | ACC_PUBLIC, INNER_CLASS_NAME_INTERNAL, null, "java/lang/Object", null); - cw.visitSource("UnbalancedMonitorsTest.java", null); + cw.visitSource("UnbalancedMonitorsTest.java", null); - cw.visitInnerClass(INNER_CLASS_NAME_INTERNAL, CLASS_NAME_INTERNAL, "UnbalancedMonitors", ACC_STATIC); + cw.visitInnerClass(INNER_CLASS_NAME_INTERNAL, CLASS_NAME_INTERNAL, "UnbalancedMonitors", ACC_STATIC); - visitConstructor(cw); - visitWrongOrder(cw); - visitBlockStructured(cw, true, false); - visitBlockStructured(cw, true, true); - visitBlockStructured(cw, false, false); - visitBlockStructured(cw, false, true); - cw.visitEnd(); + visitConstructor(cw); + visitWrongOrder(cw); + visitBlockStructured(cw, true, false); + visitBlockStructured(cw, true, true); + visitBlockStructured(cw, false, false); + visitBlockStructured(cw, false, true); + cw.visitEnd(); - return cw.toByteArray(); - } + return cw.toByteArray(); + } - private static void visitBlockStructured(ClassWriter cw, boolean normalReturnError, boolean tooMany) { - String name = (tooMany ? "tooMany" : "tooFew") + "Exits" + (normalReturnError ? "" : "Exceptional"); - // Generate too many or too few exits down the either the normal or exceptional return paths - int exceptionalExitCount = normalReturnError ? 1 : (tooMany ? 2 : 0); - int normalExitCount = normalReturnError ? (tooMany ? 2 : 0) : 1; - MethodVisitor mv; - mv = cw.visitMethod(ACC_PUBLIC, name, "(Ljava/lang/Object;Ljava/lang/Object;)Z", null, null); - mv.visitCode(); - Label l0 = new Label(); - Label l1 = new Label(); - Label l2 = new Label(); - mv.visitTryCatchBlock(l0, l1, l2, null); - Label l3 = new Label(); - mv.visitTryCatchBlock(l2, l3, l2, null); - Label l4 = new Label(); - Label l5 = new Label(); - Label l6 = new Label(); - mv.visitTryCatchBlock(l4, l5, l6, null); - Label l7 = new Label(); - mv.visitTryCatchBlock(l2, l7, l6, null); - Label l8 = new Label(); - mv.visitLabel(l8); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(DUP); - mv.visitVarInsn(ASTORE, 3); - mv.visitInsn(MONITORENTER); - mv.visitLabel(l4); - mv.visitVarInsn(ALOAD, 2); - mv.visitInsn(DUP); - mv.visitVarInsn(ASTORE, 4); - mv.visitInsn(MONITORENTER); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 2); - mv.visitVarInsn(ALOAD, 1); - mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false); - mv.visitVarInsn(ALOAD, 4); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l1); - for (int i = 0; i < normalExitCount; i++) { + private static void visitBlockStructured(ClassWriter cw, boolean normalReturnError, boolean tooMany) { + String name = (tooMany ? "tooMany" : "tooFew") + "Exits" + (normalReturnError ? "" : "Exceptional"); + // Generate too many or too few exits down the either the normal or exceptional return + // paths + int exceptionalExitCount = normalReturnError ? 1 : (tooMany ? 2 : 0); + int normalExitCount = normalReturnError ? (tooMany ? 2 : 0) : 1; + MethodVisitor mv; + mv = cw.visitMethod(ACC_PUBLIC, name, "(Ljava/lang/Object;Ljava/lang/Object;)Z", null, null); + mv.visitCode(); + Label l0 = new Label(); + Label l1 = new Label(); + Label l2 = new Label(); + mv.visitTryCatchBlock(l0, l1, l2, null); + Label l3 = new Label(); + mv.visitTryCatchBlock(l2, l3, l2, null); + Label l4 = new Label(); + Label l5 = new Label(); + Label l6 = new Label(); + mv.visitTryCatchBlock(l4, l5, l6, null); + Label l7 = new Label(); + mv.visitTryCatchBlock(l2, l7, l6, null); + Label l8 = new Label(); + mv.visitLabel(l8); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 3); + mv.visitInsn(MONITORENTER); + mv.visitLabel(l4); + mv.visitVarInsn(ALOAD, 2); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 4); + mv.visitInsn(MONITORENTER); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 2); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Object", "equals", "(Ljava/lang/Object;)Z", false); + mv.visitVarInsn(ALOAD, 4); + mv.visitInsn(MONITOREXIT); + mv.visitLabel(l1); + for (int i = 0; i < normalExitCount; i++) { + mv.visitVarInsn(ALOAD, 3); + mv.visitInsn(MONITOREXIT); + } + mv.visitLabel(l5); + mv.visitInsn(IRETURN); + mv.visitLabel(l2); + mv.visitFrame(Opcodes.F_FULL, 5, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object", + "java/lang/Object"}, 1, new Object[]{"java/lang/Throwable"}); + mv.visitVarInsn(ALOAD, 4); + mv.visitInsn(MONITOREXIT); + mv.visitLabel(l3); + mv.visitInsn(ATHROW); + mv.visitLabel(l6); + mv.visitFrame(Opcodes.F_FULL, 4, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object"}, 1, + new Object[]{"java/lang/Throwable"}); + for (int i = 0; i < exceptionalExitCount; i++) { + mv.visitVarInsn(ALOAD, 3); + mv.visitInsn(MONITOREXIT); + } + mv.visitLabel(l7); + mv.visitInsn(ATHROW); + Label l9 = new Label(); + mv.visitLabel(l9); + mv.visitMaxs(2, 5); + mv.visitEnd(); + } + + private static void visitWrongOrder(ClassWriter cw) { + MethodVisitor mv; + mv = cw.visitMethod(ACC_PUBLIC, "wrongOrder", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", null, null); + mv.visitCode(); + Label l0 = new Label(); + Label l1 = new Label(); + Label l2 = new Label(); + mv.visitTryCatchBlock(l0, l1, l2, null); + Label l3 = new Label(); + mv.visitTryCatchBlock(l2, l3, l2, null); + Label l4 = new Label(); + Label l5 = new Label(); + Label l6 = new Label(); + mv.visitTryCatchBlock(l4, l5, l6, null); + Label l7 = new Label(); + mv.visitTryCatchBlock(l2, l7, l6, null); + Label l8 = new Label(); + mv.visitLabel(l8); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 3); + mv.visitInsn(MONITORENTER); + mv.visitLabel(l4); + mv.visitVarInsn(ALOAD, 2); + mv.visitInsn(DUP); + mv.visitVarInsn(ASTORE, 4); + mv.visitInsn(MONITORENTER); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 2); mv.visitVarInsn(ALOAD, 3); mv.visitInsn(MONITOREXIT); - } - mv.visitLabel(l5); - mv.visitInsn(IRETURN); - mv.visitLabel(l2); - mv.visitFrame(Opcodes.F_FULL, 5, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object", - "java/lang/Object"}, 1, new Object[]{"java/lang/Throwable"}); - mv.visitVarInsn(ALOAD, 4); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l3); - mv.visitInsn(ATHROW); - mv.visitLabel(l6); - mv.visitFrame(Opcodes.F_FULL, 4, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object"}, 1, - new Object[]{"java/lang/Throwable"}); - for (int i = 0; i < exceptionalExitCount; i++) { + mv.visitLabel(l1); + // Swapped exit order with exit above + mv.visitVarInsn(ALOAD, 4); + mv.visitInsn(MONITOREXIT); + mv.visitLabel(l5); + mv.visitInsn(ARETURN); + mv.visitLabel(l2); + mv.visitFrame(Opcodes.F_FULL, 5, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object", + "java/lang/Object"}, 1, new Object[]{"java/lang/Throwable"}); + mv.visitVarInsn(ALOAD, 4); + mv.visitInsn(MONITOREXIT); + mv.visitLabel(l3); + mv.visitInsn(ATHROW); + mv.visitLabel(l6); + mv.visitFrame(Opcodes.F_FULL, 4, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object"}, 1, + new Object[]{"java/lang/Throwable"}); mv.visitVarInsn(ALOAD, 3); mv.visitInsn(MONITOREXIT); + mv.visitLabel(l7); + mv.visitInsn(ATHROW); + Label l9 = new Label(); + mv.visitLabel(l9); + mv.visitMaxs(2, 5); + mv.visitEnd(); } - mv.visitLabel(l7); - mv.visitInsn(ATHROW); - Label l9 = new Label(); - mv.visitLabel(l9); - mv.visitMaxs(2, 5); - mv.visitEnd(); - } - private static void visitWrongOrder(ClassWriter cw) { - MethodVisitor mv; - mv = cw.visitMethod(ACC_PUBLIC, "wrongOrder", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", null, null); - mv.visitCode(); - Label l0 = new Label(); - Label l1 = new Label(); - Label l2 = new Label(); - mv.visitTryCatchBlock(l0, l1, l2, null); - Label l3 = new Label(); - mv.visitTryCatchBlock(l2, l3, l2, null); - Label l4 = new Label(); - Label l5 = new Label(); - Label l6 = new Label(); - mv.visitTryCatchBlock(l4, l5, l6, null); - Label l7 = new Label(); - mv.visitTryCatchBlock(l2, l7, l6, null); - Label l8 = new Label(); - mv.visitLabel(l8); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(DUP); - mv.visitVarInsn(ASTORE, 3); - mv.visitInsn(MONITORENTER); - mv.visitLabel(l4); - mv.visitVarInsn(ALOAD, 2); - mv.visitInsn(DUP); - mv.visitVarInsn(ASTORE, 4); - mv.visitInsn(MONITORENTER); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 2); - mv.visitVarInsn(ALOAD, 3); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l1); - // Swapped exit order with exit above - mv.visitVarInsn(ALOAD, 4); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l5); - mv.visitInsn(ARETURN); - mv.visitLabel(l2); - mv.visitFrame(Opcodes.F_FULL, 5, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object", - "java/lang/Object"}, 1, new Object[]{"java/lang/Throwable"}); - mv.visitVarInsn(ALOAD, 4); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l3); - mv.visitInsn(ATHROW); - mv.visitLabel(l6); - mv.visitFrame(Opcodes.F_FULL, 4, new Object[]{INNER_CLASS_NAME_INTERNAL, "java/lang/Object", "java/lang/Object", "java/lang/Object"}, 1, - new Object[]{"java/lang/Throwable"}); - mv.visitVarInsn(ALOAD, 3); - mv.visitInsn(MONITOREXIT); - mv.visitLabel(l7); - mv.visitInsn(ATHROW); - Label l9 = new Label(); - mv.visitLabel(l9); - mv.visitMaxs(2, 5); - mv.visitEnd(); - } - - private static void visitConstructor(ClassWriter cw) { - MethodVisitor mv; - mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); - mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitInsn(RETURN); - Label l2 = new Label(); - mv.visitLabel(l2); - mv.visitMaxs(1, 1); - mv.visitEnd(); + private static void visitConstructor(ClassWriter cw) { + MethodVisitor mv; + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + Label l0 = new Label(); + mv.visitLabel(l0); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + Label l1 = new Label(); + mv.visitLabel(l1); + mv.visitInsn(RETURN); + Label l2 = new Label(); + mv.visitLabel(l2); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } } public static class AsmLoader extends ClassLoader { @@ -308,7 +314,7 @@ public class UnbalancedMonitorsTest extends GraalCompilerTest implements Opcodes if (loaded != null) { return loaded; } - byte[] bytes = generateClass(); + byte[] bytes = Gen.generateClass(); return (loaded = defineClass(name, bytes, 0, bytes.length)); } else { return super.findClass(name); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java index 7e8914b2991..7e685a24492 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeReadEliminationTest.java @@ -22,11 +22,6 @@ */ package org.graalvm.compiler.core.test; -import java.lang.reflect.Field; - -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; @@ -34,27 +29,19 @@ import org.graalvm.compiler.nodes.extended.UnsafeAccessNode; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.junit.Assert; +import org.junit.Test; import sun.misc.Unsafe; public class UnsafeReadEliminationTest extends GraalCompilerTest { - public static final Unsafe UNSAFE; - static { - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - UNSAFE = (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("Exception while trying to get Unsafe", e); - } - } - public static long[] Memory = new long[]{1, 2}; public static double SideEffectD; public static double SideEffectL; @@ -129,15 +116,16 @@ public class UnsafeReadEliminationTest extends GraalCompilerTest { } public void testPartialEscapeReadElimination(StructuredGraph graph, int reads, int writes) { + OptionValues options = graph.getOptions(); PhaseContext context = getDefaultHighTierContext(); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); canonicalizer.apply(graph, context); - new PartialEscapePhase(true, true, canonicalizer, null).apply(graph, context); + new PartialEscapePhase(true, true, canonicalizer, null, options).apply(graph, context); Assert.assertEquals(3, graph.getNodes().filter(UnsafeAccessNode.class).count()); // after lowering the same applies for reads and writes new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); canonicalizer.apply(graph, context); - new PartialEscapePhase(true, true, canonicalizer, null).apply(graph, context); + new PartialEscapePhase(true, true, canonicalizer, null, options).apply(graph, context); Assert.assertEquals(reads, graph.getNodes().filter(ReadNode.class).count()); Assert.assertEquals(writes, graph.getNodes().filter(WriteNode.class).count()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java new file mode 100644 index 00000000000..236be5cff40 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import java.lang.reflect.Field; + +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.junit.Test; + +public class UnsafeVirtualizationTest extends GraalCompilerTest { + + public static class A { + int f1; + int f2; + } + + private static final long AF1Offset; + private static final long AF2Offset; + static { + long o1 = -1; + long o2 = -1; + try { + Field f1 = A.class.getDeclaredField("f1"); + Field f2 = A.class.getDeclaredField("f2"); + o1 = UNSAFE.objectFieldOffset(f1); + o2 = UNSAFE.objectFieldOffset(f2); + } catch (NoSuchFieldException | SecurityException e) { + throw new AssertionError(e); + } + AF1Offset = o1; + AF2Offset = o2; + } + + public static int unsafeSnippet0(int i1, int i2) { + A a = new A(); + UNSAFE.putDouble(a, AF1Offset, i1 + i2); + return UNSAFE.getInt(a, AF1Offset) + UNSAFE.getInt(a, AF2Offset); + } + + public static int unsafeSnippet1(int i1, int i2) { + A a = new A(); + UNSAFE.putDouble(a, AF1Offset, i1 + i2); + a.f2 = i1; + return (int) UNSAFE.getDouble(a, AF1Offset); + } + + @Test + public void testUnsafePEA01() { + testPartialEscapeReadElimination(parseEager("unsafeSnippet0", AllowAssumptions.NO), false); + testPartialEscapeReadElimination(parseEager("unsafeSnippet0", AllowAssumptions.NO), true); + } + + @Test + public void testUnsafePEA02() { + testPartialEscapeReadElimination(parseEager("unsafeSnippet1", AllowAssumptions.NO), false); + testPartialEscapeReadElimination(parseEager("unsafeSnippet1", AllowAssumptions.NO), true); + } + + public void testPartialEscapeReadElimination(StructuredGraph graph, boolean canonicalizeBefore) { + OptionValues options = graph.getOptions(); + PhaseContext context = getDefaultHighTierContext(); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + if (canonicalizeBefore) { + canonicalizer.apply(graph, context); + } + new PartialEscapePhase(true, true, canonicalizer, null, options).apply(graph, context); + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnusedArray.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnusedArray.java new file mode 100644 index 00000000000..273d1404b18 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnusedArray.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import static org.graalvm.compiler.graph.test.matchers.NodeIterableIsEmpty.isEmpty; +import static org.junit.Assert.assertThat; + +import org.graalvm.compiler.graph.iterators.NodeIterable; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.java.NewArrayNode; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; + +public class UnusedArray extends GraalCompilerTest { + @SuppressWarnings("unused") + public void smallArray() { + byte[] array = new byte[3]; + } + + @SuppressWarnings("unused") + public void largeArray() { + byte[] array = new byte[10 * 1024 * 1024]; + } + + @SuppressWarnings("unused") + public void unknownArray(int l) { + byte[] array = new byte[l]; + } + + @Test + public void testSmall() { + test("smallArray"); + } + + @Test + public void testLarge() { + test("largeArray"); + } + + @Test + public void testUnknown() { + test("unknownArray"); + } + + public void test(String method) { + StructuredGraph graph = parseEager(method, StructuredGraph.AllowAssumptions.YES); + new CanonicalizerPhase().apply(graph, new PhaseContext(getProviders())); + NodeIterable newArrayNodes = graph.getNodes().filter(NewArrayNode.class); + assertThat(newArrayNodes, isEmpty()); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java index ff82e1aabf2..809089fb8d1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyBailoutUsageTest.java @@ -22,25 +22,24 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import org.junit.Test; - import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.common.PermanentBailoutException; -import org.graalvm.compiler.common.RetryableBailoutException; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; +import org.graalvm.compiler.core.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.RetryableBailoutException; +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.PhaseSuite; @@ -49,6 +48,7 @@ import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.phases.verify.VerifyBailoutUsage; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.junit.Test; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.meta.MetaAccessProvider; @@ -126,12 +126,14 @@ public class VerifyBailoutUsageTest { GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true); graphBuilderSuite.appendPhase(new GraphBuilderPhase(config)); HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE); + OptionValues options = getInitialOptions(); + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); for (Method m : c.getDeclaredMethods()) { if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build(); graphBuilderSuite.apply(graph, context); - try (DebugConfigScope s = Debug.disableIntercept()) { + try (DebugCloseable s = debug.disableIntercept()) { new VerifyBailoutUsage().apply(graph, context); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java index 47aba0895c8..ae3de81dc20 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyDebugUsageTest.java @@ -22,25 +22,24 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import org.junit.Test; - import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.PhaseSuite; @@ -49,6 +48,7 @@ import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.phases.verify.VerifyDebugUsage; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.junit.Test; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -59,8 +59,9 @@ public class VerifyDebugUsageTest { @Override protected void run(StructuredGraph graph) { + DebugContext debug = graph.getDebug(); for (Node n : graph.getNodes()) { - Debug.log("%s", n.toString()); + debug.log("%s", n.toString()); } } @@ -71,9 +72,10 @@ public class VerifyDebugUsageTest { @Override @SuppressWarnings("try") protected void run(StructuredGraph graph) { - try (Indent i = Debug.logAndIndent("%s", graph.toString())) { + DebugContext debug = graph.getDebug(); + try (Indent i = debug.logAndIndent("%s", graph.toString())) { for (Node n : graph.getNodes()) { - Debug.log("%s", n); + debug.log("%s", n); } } } @@ -84,16 +86,39 @@ public class VerifyDebugUsageTest { @Override protected void run(StructuredGraph graph) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "%s", graph.toString()); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "%s", graph.toString()); + } + } + + private static class InvalidDumpLevelPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.VERY_DETAILED_LEVEL + 1, graph, "%s", graph); + } + } + + private static class NonConstantDumpLevelPhase extends Phase { + + @Override + protected void run(StructuredGraph graph) { + DebugContext debug = graph.getDebug(); + debug.dump(getLevel(), graph, "%s", graph); } + int getLevel() { + return 10; + } } private static class InvalidVerifyUsagePhase extends Phase { @Override protected void run(StructuredGraph graph) { - Debug.verify(graph, "%s", graph.toString()); + DebugContext debug = graph.getDebug(); + debug.verify(graph, "%s", graph.toString()); } } @@ -102,8 +127,9 @@ public class VerifyDebugUsageTest { @Override protected void run(StructuredGraph graph) { + DebugContext debug = graph.getDebug(); for (Node n : graph.getNodes()) { - Debug.log("error " + n); + debug.log("error " + n); } } @@ -114,9 +140,10 @@ public class VerifyDebugUsageTest { @Override @SuppressWarnings("try") protected void run(StructuredGraph graph) { - try (Indent i = Debug.logAndIndent("error " + graph)) { + DebugContext debug = graph.getDebug(); + try (Indent i = debug.logAndIndent("error " + graph)) { for (Node n : graph.getNodes()) { - Debug.log("%s", n); + debug.log("%s", n); } } } @@ -127,7 +154,8 @@ public class VerifyDebugUsageTest { @Override protected void run(StructuredGraph graph) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "error " + graph); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "error " + graph); } } @@ -136,7 +164,8 @@ public class VerifyDebugUsageTest { @Override protected void run(StructuredGraph graph) { - Debug.verify(graph, "error " + graph); + DebugContext debug = graph.getDebug(); + debug.verify(graph, "error " + graph); } } @@ -145,8 +174,9 @@ public class VerifyDebugUsageTest { @Override protected void run(StructuredGraph graph) { + DebugContext debug = graph.getDebug(); for (Node n : graph.getNodes()) { - Debug.log("%s", n); + debug.log("%s", n); } } @@ -157,9 +187,10 @@ public class VerifyDebugUsageTest { @Override @SuppressWarnings("try") protected void run(StructuredGraph graph) { - try (Indent i = Debug.logAndIndent("%s", graph)) { + DebugContext debug = graph.getDebug(); + try (Indent i = debug.logAndIndent("%s", graph)) { for (Node n : graph.getNodes()) { - Debug.log("%s", n); + debug.log("%s", n); } } } @@ -170,7 +201,8 @@ public class VerifyDebugUsageTest { @Override protected void run(StructuredGraph graph) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "%s", graph); + DebugContext debug = graph.getDebug(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "%s", graph); } } @@ -179,7 +211,8 @@ public class VerifyDebugUsageTest { @Override protected void run(StructuredGraph graph) { - Debug.verify(graph, "%s", graph); + DebugContext debug = graph.getDebug(); + debug.verify(graph, "%s", graph); } } @@ -187,7 +220,7 @@ public class VerifyDebugUsageTest { private static class InvalidGraalErrorGuaranteePhase extends Phase { @Override protected void run(StructuredGraph graph) { - GraalError.guarantee(graph.getNodes().count() > 0, "Graph must contain nodes %s %s %s", graph, graph, graph, graph.toString()); + GraalError.guarantee(graph.getNodes().count() > 0, "Graph must contain nodes %s %s %s", graph, graph, graph.toString()); } } @@ -234,6 +267,16 @@ public class VerifyDebugUsageTest { testDebugUsageClass(InvalidDumpUsagePhase.class); } + @Test(expected = VerificationError.class) + public void testDumpLevelInvalid() { + testDebugUsageClass(InvalidDumpLevelPhase.class); + } + + @Test(expected = VerificationError.class) + public void testDumpNonConstantLevelInvalid() { + testDebugUsageClass(NonConstantDumpLevelPhase.class); + } + @Test(expected = VerificationError.class) public void testLogInvalidConcat() { testDebugUsageClass(InvalidConcatLogUsagePhase.class); @@ -304,12 +347,14 @@ public class VerifyDebugUsageTest { GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true); graphBuilderSuite.appendPhase(new GraphBuilderPhase(config)); HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE); + OptionValues options = getInitialOptions(); + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); for (Method m : c.getDeclaredMethods()) { if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build(); graphBuilderSuite.apply(graph, context); - try (DebugConfigScope s = Debug.disableIntercept()) { + try (DebugCloseable s = debug.disableIntercept()) { new VerifyDebugUsage().apply(graph, context); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java index 0b6669b70a5..c3d2e33397a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/VerifyVirtualizableTest.java @@ -22,25 +22,23 @@ */ package org.graalvm.compiler.core.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import org.junit.Test; - import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.java.GraphBuilderPhase; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; @@ -48,6 +46,7 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.spi.Virtualizable; import org.graalvm.compiler.nodes.spi.VirtualizerTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.VerifyPhase.VerificationError; @@ -55,6 +54,7 @@ import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.phases.verify.VerifyVirtualizableUsage; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.junit.Test; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -271,12 +271,14 @@ public class VerifyVirtualizableTest { GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true); graphBuilderSuite.appendPhase(new GraphBuilderPhase(config)); HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE); + OptionValues options = getInitialOptions(); + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); for (Method m : c.getDeclaredMethods()) { if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build(); graphBuilderSuite.apply(graph, context); - try (DebugConfigScope s = Debug.disableIntercept()) { + try (DebugCloseable s = debug.disableIntercept()) { new VerifyVirtualizableUsage().apply(graph, context); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ZeroSignExtendTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ZeroSignExtendTest.java new file mode 100644 index 00000000000..cd9a718785a --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ZeroSignExtendTest.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test; + +import org.junit.Test; + +/* + * Test compilation of ZeroExtend and SignExtend nodes + */ + +public class ZeroSignExtendTest extends GraalCompilerTest { + + int testSnippet1(char[] chars) { + int x = 1; + x += chars[0]; + x -= chars[1]; + x *= chars[2]; + x /= chars[3]; + x &= chars[4]; + x |= chars[5]; + x ^= chars[6]; + x <<= chars[7]; + x >>= (chars[8] - chars[0]); + x >>>= (chars[9] - chars[0]); + x += chars[1]; + return x; + } + + long testSnippet2(char[] chars) { + long y = 2; + y += chars[0]; + y -= chars[1]; + y *= chars[2]; + y /= chars[3]; + y &= chars[4]; + y |= chars[5]; + y ^= chars[6]; + y <<= chars[7]; + y >>= (chars[8] - chars[0]); + y >>>= (chars[9] - chars[0]); + y += chars[1]; + return y; + } + + int testSnippet3(short[] shorts) { + int x = 1; + x += shorts[0]; + x -= shorts[1]; + x *= shorts[2]; + x /= shorts[3]; + x &= shorts[4]; + x |= shorts[5]; + x ^= shorts[6]; + x <<= shorts[7]; + x >>= (shorts[8] - shorts[0]); + x >>>= (shorts[9] - shorts[0]); + x += shorts[1]; + return x; + } + + long testSnippet4(short[] shorts) { + long y = 2; + y += shorts[0]; + y -= shorts[1]; + y *= shorts[2]; + y /= shorts[3]; + y &= shorts[4]; + y |= shorts[5]; + y ^= shorts[6]; + y <<= shorts[7]; + y >>= (shorts[8] - shorts[0]); + y >>>= (shorts[9] - shorts[0]); + y += shorts[1]; + return y; + } + + int testSnippet5(byte[] bytes) { + int x = 1; + x += bytes[0]; + x -= bytes[1]; + x *= bytes[2]; + x /= bytes[3]; + x &= bytes[4]; + x |= bytes[5]; + x ^= bytes[6]; + x <<= bytes[7]; + x >>= (bytes[8] - bytes[0]); + x >>>= (bytes[9] - bytes[0]); + x += bytes[1]; + return x; + } + + long testSnippet6(byte[] bytes) { + long y = 2; + y += bytes[0]; + y -= bytes[1]; + y *= bytes[2]; + y /= bytes[3]; + y &= bytes[4]; + y |= bytes[5]; + y ^= bytes[6]; + y <<= bytes[7]; + y >>= (bytes[8] - bytes[0]); + y >>>= (bytes[9] - bytes[0]); + y += bytes[1]; + return y; + } + + @Test + + public void test() { + char[] input1 = new char[]{'0', '1', '2', '3', '4', '5', '7', '8', '9', 'A'}; + char[] input2 = new char[]{'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'}; + + short[] input3 = new short[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + short[] input4 = new short[]{11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; + + byte[] input5 = new byte[]{21, 22, 23, 24, 25, 26, 27, 28, 29, 30}; + byte[] input6 = new byte[]{11, 12, 13, 14, 15, 16, 17, 18, 19, 40}; + + test("testSnippet1", input1); + test("testSnippet2", input2); + test("testSnippet3", input3); + test("testSnippet4", input4); + test("testSnippet5", input5); + test("testSnippet6", input6); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/AllocatorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/AllocatorTest.java index daa6e062861..cf3d5811ea8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/AllocatorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/AllocatorTest.java @@ -24,15 +24,8 @@ package org.graalvm.compiler.core.test.backend; import java.util.HashSet; -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.ValueUtil; -import jdk.vm.ci.meta.Value; - -import org.junit.Assert; - import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRValueUtil; @@ -40,23 +33,29 @@ import org.graalvm.compiler.lir.StandardOp.ValueMoveOp; import org.graalvm.compiler.lir.ValueProcedure; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.junit.Assert; + +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.ValueUtil; +import jdk.vm.ci.meta.Value; public class AllocatorTest extends BackendTest { @SuppressWarnings("try") protected void testAllocation(String snippet, final int expectedRegisters, final int expectedRegRegMoves, final int expectedSpillMoves) { final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); - try (Scope s = Debug.scope("AllocatorTest", graph, graph.method(), getCodeCache())) { + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope s = debug.scope("AllocatorTest", graph, graph.method(), getCodeCache())) { final RegisterStats stats = new RegisterStats(getLIRGenerationResult(graph).getLIR()); - try (Scope s2 = Debug.scope("Assertions", stats.lir)) { + try (DebugContext.Scope s2 = debug.scope("Assertions", stats.lir)) { Assert.assertEquals("register count", expectedRegisters, stats.registers.size()); Assert.assertEquals("reg-reg moves", expectedRegRegMoves, stats.regRegMoves); Assert.assertEquals("spill moves", expectedSpillMoves, stats.spillMoves); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } @@ -91,8 +90,8 @@ public class AllocatorTest extends BackendTest { private void collectStats(final LIRInstruction instr) { instr.forEachOutput(collectStatsProc); - if (instr instanceof ValueMoveOp) { - ValueMoveOp move = (ValueMoveOp) instr; + if (ValueMoveOp.isValueMoveOp(instr)) { + ValueMoveOp move = ValueMoveOp.asValueMoveOp(instr); Value def = move.getResult(); Value use = move.getInput(); if (ValueUtil.isRegister(def)) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java index 5f689224d48..0d33c8f532e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java @@ -22,16 +22,15 @@ */ package org.graalvm.compiler.core.test.backend; -import jdk.vm.ci.code.Architecture; - import org.graalvm.compiler.core.GraalCompiler; import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.phases.OptimisticOptimizations; +import jdk.vm.ci.code.Architecture; + public abstract class BackendTest extends GraalCompilerTest { public BackendTest() { @@ -44,13 +43,14 @@ public abstract class BackendTest extends GraalCompilerTest { @SuppressWarnings("try") protected LIRGenerationResult getLIRGenerationResult(final StructuredGraph graph) { - try (Scope s = Debug.scope("FrontEnd")) { - GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE, graph.getProfilingInfo(), getSuites()); + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope s = debug.scope("FrontEnd")) { + GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE, graph.getProfilingInfo(), createSuites(graph.getOptions())); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } - LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), graph, null, null, getLIRSuites()); + LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), graph, null, null, createLIRSuites(graph.getOptions())); return lirGen; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest.java deleted file mode 100644 index 5704e05f80b..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest.java +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.test.debug; - -import java.io.PrintStream; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.ListIterator; -import java.util.Map; -import java.util.stream.Collectors; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugConfigScope; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugDumpHandler; -import org.graalvm.compiler.debug.DebugMethodMetrics; -import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.DebugVerifyHandler; -import org.graalvm.compiler.debug.DelegatingDebugConfig; -import org.graalvm.compiler.debug.DelegatingDebugConfig.Feature; -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.internal.DebugScope; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl.CompilationData; -import org.graalvm.compiler.debug.internal.method.MethodMetricsInlineeScopeInfo; -import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; -import org.graalvm.compiler.nodes.InvokeNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.calc.BinaryNode; -import org.graalvm.compiler.nodes.calc.FixedBinaryNode; -import org.graalvm.compiler.nodes.calc.MulNode; -import org.graalvm.compiler.nodes.calc.ShiftNode; -import org.graalvm.compiler.nodes.calc.SignedDivNode; -import org.graalvm.compiler.nodes.calc.SubNode; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; -import org.graalvm.compiler.phases.BasePhase; -import org.graalvm.compiler.phases.Phase; -import org.graalvm.compiler.phases.PhaseSuite; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; -import org.graalvm.compiler.phases.schedule.SchedulePhase; -import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; -import org.graalvm.compiler.phases.tiers.HighTierContext; -import org.graalvm.compiler.phases.tiers.Suites; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public abstract class MethodMetricsTest extends GraalCompilerTest { - static class TestApplication { - public static int m01(int x, int y) { - return x + y; - } - - public static int m02(int x, int y) { - return x * y; - } - - public static int m03(int x, int y) { - return x ^ y; - } - - public static int m04(int x, int y) { - return x >> y; - } - - public static int m05(int x, int y) { - return x >>> y; - } - - public static int m06(int x, int y) { - return x << y; - } - - public static int m07(int x, int y) { - return x > y ? 0 : 1; - } - - public static int m08(int x, int y) { - return x % y; - } - - public static int m09(int x, int y) { - return x / y; - } - - public static int m10(int x, int y) { - return x - y; - } - - } - - public static final Class[] testSignature = new Class[]{int.class, int.class}; - public static final Object[] testArgs = new Object[]{10, 10}; - - static class MethodMetricPhases { - static class CountingAddPhase extends Phase { - - // typically those global metrics would be static final, but we need new timers every - // invocation if we override the debugvaluefactory - private final DebugCounter globalCounter = Debug.counter("GlobalMetric"); - private final DebugTimer globalTimer = Debug.timer("GlobalTimer"); - - @Override - @SuppressWarnings("try") - protected void run(StructuredGraph graph) { - try (DebugCloseable d = globalTimer.start()) { - ResolvedJavaMethod method = graph.method(); - DebugMethodMetrics mm = Debug.methodMetrics(method); - mm.addToMetric(graph.getNodes().filter(InvokeNode.class).count(), "Invokes"); - mm.incrementMetric("PhaseRunsOnMethod"); - globalCounter.increment(); - } - } - } - - static class CountingShiftPhase extends Phase { - @Override - protected void run(StructuredGraph graph) { - Debug.methodMetrics(graph.method()).addToMetric(graph.getNodes().filter(ShiftNode.class).count(), "Shifts"); - } - } - - static class CountingMulPhase extends Phase { - @Override - protected void run(StructuredGraph graph) { - Debug.methodMetrics(graph.method()).addToMetric(graph.getNodes().filter(MulNode.class).count(), "Muls"); - } - } - - static class CountingSubPhase extends Phase { - @Override - protected void run(StructuredGraph graph) { - Debug.methodMetrics(graph.method()).addToMetric(graph.getNodes().filter(SubNode.class).count(), "Subs"); - } - } - - static class CountingDivPhase extends Phase { - @Override - protected void run(StructuredGraph graph) { - Debug.methodMetrics(graph.method()).addToMetric(graph.getNodes().filter(SignedDivNode.class).count(), "Divs"); - } - } - - static class CountingBinOpPhase extends Phase { - @Override - protected void run(StructuredGraph graph) { - Debug.methodMetrics(graph.method()).addToMetric(graph.getNodes().filter(x -> x instanceof BinaryNode || x instanceof FixedBinaryNode).count(), "BinOps"); - } - } - - static class ScopeTestPhase extends Phase { - // typically those global metrics would be static final, but we need new timers every - // invocation if we override the debugvaluefactory - private final DebugTimer timer = Debug.timer("GlobalTimer1"); - private final DebugTimer scopedTimer = Debug.timer("GlobalTimer2"); - private final DebugTimer scopedScopedTimer = Debug.timer("GlobalTimer3"); - private final DebugTimer scopedScopedScopeTimer = Debug.timer("GlobalTimer4"); - - private final DebugTimer timer1 = Debug.timer("GlobalTimer1_WithoutInlineEnhancement"); - private final DebugTimer scopedTimer1 = Debug.timer("GlobalTimer2_WithoutInlineEnhancement"); - private final DebugTimer scopedScopedTimer1 = Debug.timer("GlobalTimer3_WithoutInlineEnhancement"); - private final DebugTimer scopedScopedScopeTimer1 = Debug.timer("GlobalTimer4_WithoutInlineEnhancement"); - - @Override - @SuppressWarnings("try") - protected void run(StructuredGraph graph) { - // we are in an enhanced debug scope from graal compiler - // now we open multiple inlining scopes, record their time - try (DebugCloseable c1 = timer.start()) { - try (DebugCloseable c2 = scopedTimer.start()) { - try (DebugCloseable c3 = scopedScopedTimer.start()) { - // do sth unnecessary long allocating many inlinee scopes - for (int i = 0; i < 50; i++) { - try (Debug.Scope s1 = Debug.methodMetricsScope("InlineEnhancement1", MethodMetricsInlineeScopeInfo.create(graph.method()), false)) { - try (DebugCloseable c4 = scopedScopedScopeTimer.start()) { - new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS).apply(graph); - // double scoped inlinee scopes should not make problems - // with the data - try (Debug.Scope s2 = Debug.methodMetricsScope("InlineEnhancement2", MethodMetricsInlineeScopeInfo.create(graph.method()), - false)) { - new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS).apply(graph); - } - } - } - } - } - } - } - - // now lets try different counters without the inline enhancement - try (DebugCloseable c1 = timer1.start()) { - try (DebugCloseable c2 = scopedTimer1.start()) { - try (DebugCloseable c3 = scopedScopedTimer1.start()) { - // do sth unnecessary long allocating many inlinee scopes - for (int i = 0; i < 50; i++) { - try (DebugCloseable c4 = scopedScopedScopeTimer1.start()) { - new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS).apply(graph); - new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS).apply(graph); - } - } - } - } - } - } - - } - } - - static DebugConfig overrideGraalDebugConfig(PrintStream log, String methodFilter, String methodMeter) { - List dumpHandlers = new ArrayList<>(); - List verifyHandlers = new ArrayList<>(); - GraalDebugConfig debugConfig = new GraalDebugConfig( - GraalDebugConfig.Options.Log.getValue(), - GraalDebugConfig.Options.Count.getValue(), - GraalDebugConfig.Options.TrackMemUse.getValue(), - GraalDebugConfig.Options.Time.getValue(), - GraalDebugConfig.Options.Dump.getValue(), - GraalDebugConfig.Options.Verify.getValue(), - methodFilter, - methodMeter, - log, dumpHandlers, verifyHandlers); - return debugConfig; - } - - private static OverrideScope overrideMetricPrinterConfig() { - Map, Object> mapping = new HashMap<>(); - mapping.put(MethodMetricsPrinter.Options.MethodMeterPrintAscii, true); - return OptionValue.override(mapping); - } - - abstract Phase additionalPhase(); - - @Override - protected Suites createSuites() { - Suites ret = super.createSuites(); - ListIterator> iter = ret.getHighTier().findPhase(ConvertDeoptimizeToGuardPhase.class, true); - PhaseSuite.findNextPhase(iter, CanonicalizerPhase.class); - iter.add(additionalPhase()); - return ret; - } - - @Test - @SuppressWarnings("try") - public void test() throws Throwable { - try (DebugConfigScope s = Debug.setConfig(getConfig()); OverrideScope o = getOScope();) { - executeMethod(TestApplication.class.getMethod("m01", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m02", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m03", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m04", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m05", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m06", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m07", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m08", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m09", testSignature), null, testArgs); - executeMethod(TestApplication.class.getMethod("m10", testSignature), null, testArgs); - assertValues(); - } - } - - @Before - public void rememberScopeId() { - scopeIdBeforeAccess = DebugScope.getCurrentGlobalScopeId(); - } - - @After - public void clearMMCache() { - MethodMetricsImpl.clearMM(); - } - - abstract DebugConfig getConfig(); - - OverrideScope getOScope() { - return overrideMetricPrinterConfig(); - } - - abstract void assertValues() throws Throwable; - - @SuppressWarnings("unchecked") - private static Map readMethodMetricsImplData() { - Map threadLocalMap = null; - for (Field f : MethodMetricsImpl.class.getDeclaredFields()) { - if (f.getName().equals("threadEntries")) { - f.setAccessible(true); - Object map; - try { - map = ((ThreadLocal) f.get(null)).get(); - } catch (Throwable t) { - throw new RuntimeException(t); - } - threadLocalMap = (Map) map; - break; - } - } - return threadLocalMap; - } - - private long scopeIdBeforeAccess; - private long scopeIdAfterAccess; - - protected long readValFromCurrThread(ResolvedJavaMethod method, String metricName) { - - Map threadLocalMap = readMethodMetricsImplData(); - assert threadLocalMap != null; - CompilationData compilationData = threadLocalMap.get(method); - assert compilationData != null; - Map> compilations = compilationData.getCompilations(); - List> compilationEntries = new ArrayList<>(); - compilations.forEach((x, y) -> { - if (x >= scopeIdBeforeAccess && x <= scopeIdAfterAccess) { - compilationEntries.add(y); - } - }); - List> listView = compilationEntries.stream().filter(x -> x.size() > 0).collect(Collectors.toList()); - assert listView.size() <= 1 : "There must be at most one none empty compilation data point present:" + listView.size(); - /* - * NOTE: Using the pre-generation of compilation entries for a method has the disadvantage - * that during testing we have different points in time when we request the metric. First, - * properly, when we use it and then when we want to know the result, but when we check the - * result the debug context no longer holds a correct scope with the unique id, so we return - * the first compilation entry that is not empty. - */ - Map entries = listView.size() > 0 ? listView.get(0) : null; - Long res = entries != null ? entries.get(metricName) : null; - return res != null ? res : 0; - } - - @SuppressWarnings("try") - void assertValues(String metricName, long[] vals) { - scopeIdAfterAccess = DebugScope.getCurrentGlobalScopeId(); - try (DebugConfigScope s = Debug.setConfig(new DelegatingDebugConfig().enable(Feature.METHOD_METRICS))) { - Assert.assertEquals(vals[0], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m01", testSignature)), metricName)); - Assert.assertEquals(vals[1], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m02", testSignature)), metricName)); - Assert.assertEquals(vals[2], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m03", testSignature)), metricName)); - Assert.assertEquals(vals[3], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m04", testSignature)), metricName)); - Assert.assertEquals(vals[4], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m05", testSignature)), metricName)); - Assert.assertEquals(vals[5], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m06", testSignature)), metricName)); - Assert.assertEquals(vals[6], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m07", testSignature)), metricName)); - Assert.assertEquals(vals[7], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m08", testSignature)), metricName)); - Assert.assertEquals(vals[8], readValFromCurrThread(asResolvedJavaMethod(TestApplication.class.getMethod("m09", testSignature)), metricName)); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - - void executeMethod(Method m, Object receiver, Object... args) { - test(asResolvedJavaMethod(m), receiver, args); - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest4.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest4.java deleted file mode 100644 index c1cffbd1bc4..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest4.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.test.debug; - -import org.junit.Test; - -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.phases.Phase; - -public class MethodMetricsTest4 extends MethodMetricsTest { - - @Override - protected Phase additionalPhase() { - return new MethodMetricPhases.CountingSubPhase(); - } - - @Override - DebugConfig getConfig() { - return overrideGraalDebugConfig(System.out, "MethodMetricsTest$TestApplication.*", "CountingSubPhase"); - } - - @Override - void assertValues() throws Throwable { - assertValues("Subs", new long[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 1}); - } - - @Override - @Test - public void test() throws Throwable { - super.test(); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest6.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest6.java deleted file mode 100644 index 068ef5874cd..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest6.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.test.debug; - -import org.junit.Test; - -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.phases.Phase; - -public class MethodMetricsTest6 extends MethodMetricsTest { - - @Override - protected Phase additionalPhase() { - return new MethodMetricPhases.CountingBinOpPhase(); - } - - @Override - DebugConfig getConfig() { - return overrideGraalDebugConfig(System.out, "MethodMetricsTest$TestApplication.*", "CountingBinOpPhase"); - } - - @Override - void assertValues() throws Throwable { - assertValues("BinOps", new long[]{1, 1, 1, 1, 1, 1, 0, 1, 1, 1}); - } - - @Override - @Test - public void test() throws Throwable { - super.test(); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception01.java deleted file mode 100644 index ba51364d087..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception01.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.test.debug; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugDumpHandler; -import org.graalvm.compiler.debug.DebugMemUseTracker; -import org.graalvm.compiler.debug.DebugMethodMetrics; -import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.DebugValueFactory; -import org.graalvm.compiler.debug.DebugVerifyHandler; -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.internal.CounterImpl; -import org.graalvm.compiler.debug.internal.MemUseTrackerImpl; -import org.graalvm.compiler.debug.internal.TimerImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; -import org.graalvm.compiler.phases.Phase; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -// intercepting metrics -public class MethodMetricsTestInterception01 extends MethodMetricsTest { - - @Override - protected Phase additionalPhase() { - return new MethodMetricPhases.CountingAddPhase(); - } - - @Override - DebugConfig getConfig() { - List dumpHandlers = new ArrayList<>(); - List verifyHandlers = new ArrayList<>(); - GraalDebugConfig debugConfig = new GraalDebugConfig( - GraalDebugConfig.Options.Log.getValue(), - "CountingAddPhase", - GraalDebugConfig.Options.TrackMemUse.getValue(), - "CountingAddPhase", - GraalDebugConfig.Options.Dump.getValue(), - GraalDebugConfig.Options.Verify.getValue(), - "MethodMetricsTest$TestApplication.*", - "CountingAddPhase", - System.out, dumpHandlers, verifyHandlers); - return debugConfig; - } - - @Override - protected OverrideScope getOScope() { - Map, Object> mapping = new HashMap<>(); - mapping.put(MethodMetricsPrinter.Options.MethodMeterPrintAscii, true); - return OptionValue.override(mapping); - } - - private DebugValueFactory factory; - - @Test - @Override - @SuppressWarnings("try") - public void test() throws Throwable { - factory = Debug.getDebugValueFactory(); - Debug.setDebugValueFactory(new DebugValueFactory() { - @Override - public DebugTimer createTimer(String name, boolean conditional) { - return new TimerImpl(name, conditional, true); - } - - @Override - public DebugCounter createCounter(String name, boolean conditional) { - return CounterImpl.create(name, conditional, true); - } - - @Override - public DebugMethodMetrics createMethodMetrics(ResolvedJavaMethod method) { - return MethodMetricsImpl.getMethodMetrics(method); - } - - @Override - public DebugMemUseTracker createMemUseTracker(String name, boolean conditional) { - return new MemUseTrackerImpl(name, conditional, true); - } - }); - super.test(); - - } - - @Override - public void afterTest() { - super.afterTest(); - Debug.setDebugValueFactory(factory); - } - - @Override - @SuppressWarnings("try") - void assertValues() throws Throwable { - assertValues("GlobalMetric", new long[]{1, 1, 1, 1, 1, 1, 1, 1, 1, 1}); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception02.java deleted file mode 100644 index e00c2c89b25..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTestInterception02.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.test.debug; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugDumpHandler; -import org.graalvm.compiler.debug.DebugMemUseTracker; -import org.graalvm.compiler.debug.DebugMethodMetrics; -import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.DebugValueFactory; -import org.graalvm.compiler.debug.DebugVerifyHandler; -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; -import org.graalvm.compiler.phases.Phase; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -// intercepting metrics -public class MethodMetricsTestInterception02 extends MethodMetricsTest { - - @Override - protected Phase additionalPhase() { - return new MethodMetricPhases.ScopeTestPhase(); - } - - private DebugValueFactory factory; - - public void setFactory() { - /* - * setting a custom debug value factory creating a constant timer for checking scope - * creation and inlining scopes with metric intercepting works - */ - factory = Debug.getDebugValueFactory(); - Debug.setDebugValueFactory(new DebugValueFactory() { - @Override - public DebugTimer createTimer(String name, boolean conditional) { - // can still use together with real timer - // TimerImpl realTimer = new TimerImpl(name, conditional, true); - return new DebugTimer() { - int runs = 0; - - // private DebugCloseable t; - - @Override - public DebugCloseable start() { - // t = realTimer.start(); - return new DebugCloseable() { - @Override - public void close() { - // t.close(); - runs++; - MethodMetricsImpl.addToCurrentScopeMethodMetrics(name, 1); - } - }; - } - - @Override - public void setConditional(boolean flag) { - - } - - @Override - public boolean isConditional() { - return false; - } - - @Override - public TimeUnit getTimeUnit() { - return TimeUnit.MILLISECONDS; - } - - @Override - public long getCurrentValue() { - return runs; - } - }; - } - - @Override - public DebugCounter createCounter(String name, boolean conditional) { - return factory.createCounter(name, conditional); - } - - @Override - public DebugMethodMetrics createMethodMetrics(ResolvedJavaMethod method) { - return factory.createMethodMetrics(method); - } - - @Override - public DebugMemUseTracker createMemUseTracker(String name, boolean conditional) { - return factory.createMemUseTracker(name, conditional); - } - }); - } - - @Override - protected OverrideScope getOScope() { - Map, Object> mapping = new HashMap<>(); - mapping.put(MethodMetricsPrinter.Options.MethodMeterPrintAscii, true); - return OptionValue.override(mapping); - } - - @Test - @Override - public void test() throws Throwable { - setFactory(); - super.test(); - } - - @Override - public void afterTest() { - super.afterTest(); - Debug.setDebugValueFactory(factory); - } - - @Override - DebugConfig getConfig() { - List dumpHandlers = new ArrayList<>(); - List verifyHandlers = new ArrayList<>(); - GraalDebugConfig debugConfig = new GraalDebugConfig( - GraalDebugConfig.Options.Log.getValue(), - ""/* unscoped meter */, - GraalDebugConfig.Options.TrackMemUse.getValue(), - ""/* unscoped time */, - GraalDebugConfig.Options.Dump.getValue(), - GraalDebugConfig.Options.Verify.getValue(), - null /* no method filter */, - "" /* unscoped method metering */, - System.out, dumpHandlers, verifyHandlers); - return debugConfig; - } - - @Override - @SuppressWarnings("try") - void assertValues() throws Throwable { - assertValues("GlobalTimer4_WithoutInlineEnhancement", new long[]{50, 50, 50, 50, 50, 50, 50, 50, 50, 50}); - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/VerifyMethodMetricsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/VerifyMethodMetricsTest.java deleted file mode 100644 index 69826384295..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/VerifyMethodMetricsTest.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.test.debug; - -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - -import org.junit.Test; - -import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; -import org.graalvm.compiler.debug.DebugMethodMetrics; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.java.GraphBuilderPhase; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; -import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.Phase; -import org.graalvm.compiler.phases.PhaseSuite; -import org.graalvm.compiler.phases.VerifyPhase.VerificationError; -import org.graalvm.compiler.phases.tiers.HighTierContext; -import org.graalvm.compiler.phases.util.Providers; -import org.graalvm.compiler.phases.verify.VerifyDebugUsage; -import org.graalvm.compiler.runtime.RuntimeProvider; - -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -/** - * - * Tests to verify that the usage of method metrics does not generate compile time overhead through - * eager evaluation of arguments. - */ -public class VerifyMethodMetricsTest { - - private static class InvalidCCP_ToString01Inc extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.incrementMetric(n.toString()); - } - } - } - - private static class InvalidCCP_Concat01Inc extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.incrementMetric("a" + n.toString()); - } - } - } - - private static class InvalidCCP_ToString02Inc extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.incrementMetric("%s", n.toString()); - } - } - } - - private static class InvalidCCP_Concat02Inc extends Phase { - private final String s = this.getClass().toGenericString(); - - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.incrementMetric("%s%s", "a" + s, n); - } - } - } - - private static class ValidCCP_ToStringInc extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.addToMetric(1, "%s", n); - } - } - } - - private static class ValidCCP_ConcatInc extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.incrementMetric("%s%s", "a", n); - } - } - } - - private static class InvalidCCP_ToString01Add extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.addToMetric(1, n.toString()); - } - } - } - - private static class InvalidCCP_Concat01Add extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.addToMetric(1, "a" + n.toString()); - } - } - } - - private static class InvalidCCP_ToString02Add extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.addToMetric(1, "%s", n.toString()); - } - } - } - - private static class InvalidCCP_Concat02Add extends Phase { - private final String s = this.getClass().toGenericString(); - - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.addToMetric(1, "%s%s", "a" + s, n); - } - } - } - - private static class ValidCCP_ToStringAdd extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.addToMetric(1, "%s", n); - } - } - } - - private static class ValidCCP_ConcatAdd extends Phase { - @Override - protected void run(StructuredGraph graph) { - DebugMethodMetrics m = Debug.methodMetrics(graph.method()); - for (Node n : graph.getNodes()) { - m.addToMetric(1, "%s%s", "a", n); - } - } - } - - @Test(expected = VerificationError.class) - public void testLogInvalidToString01Add() { - testDebugUsageClass(InvalidCCP_ToString01Add.class); - } - - @Test(expected = VerificationError.class) - public void testLogInvalidConcat01Add() { - testDebugUsageClass(InvalidCCP_Concat01Add.class); - } - - @Test(expected = VerificationError.class) - public void testLogInvalidToString02Add() { - testDebugUsageClass(InvalidCCP_ToString02Add.class); - } - - @Test(expected = VerificationError.class) - public void testLogInvalidConcat02Add() { - testDebugUsageClass(InvalidCCP_Concat02Add.class); - } - - @Test - public void testLogValidToStringAdd() { - testDebugUsageClass(ValidCCP_ToStringAdd.class); - } - - @Test - public void testLogValidConcatAdd() { - testDebugUsageClass(ValidCCP_ConcatAdd.class); - } - - @Test(expected = VerificationError.class) - public void testLogInvalidToString01Inc() { - testDebugUsageClass(InvalidCCP_ToString01Inc.class); - } - - @Test(expected = VerificationError.class) - public void testLogInvalidConcat01Inc() { - testDebugUsageClass(InvalidCCP_Concat01Inc.class); - } - - @Test(expected = VerificationError.class) - public void testLogInvalidToString02Inc() { - testDebugUsageClass(InvalidCCP_ToString02Inc.class); - } - - @Test(expected = VerificationError.class) - public void testLogInvalidConcat02Inc() { - testDebugUsageClass(InvalidCCP_Concat02Inc.class); - } - - @Test - public void testLogValidToStringInc() { - testDebugUsageClass(ValidCCP_ToStringInc.class); - } - - @Test - public void testLogValidConcatInc() { - testDebugUsageClass(ValidCCP_ConcatInc.class); - } - - @SuppressWarnings("try") - private static void testDebugUsageClass(Class c) { - RuntimeProvider rt = Graal.getRequiredCapability(RuntimeProvider.class); - Providers providers = rt.getHostBackend().getProviders(); - MetaAccessProvider metaAccess = providers.getMetaAccess(); - PhaseSuite graphBuilderSuite = new PhaseSuite<>(); - Plugins plugins = new Plugins(new InvocationPlugins()); - GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true); - graphBuilderSuite.appendPhase(new GraphBuilderPhase(config)); - HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE); - for (Method m : c.getDeclaredMethods()) { - if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) { - ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); - graphBuilderSuite.apply(graph, context); - try (DebugConfigScope s = Debug.disableIntercept()) { - new VerifyDebugUsage().apply(graph, context); - } - } - } - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/MonitorDeoptTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/MonitorDeoptTest.java index 1075fbb9b52..24d463918fb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/MonitorDeoptTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/MonitorDeoptTest.java @@ -189,7 +189,7 @@ public final class MonitorDeoptTest extends GraalCompilerTest { removeLoopSafepoint(graph); CompilationResult compilationResult = compile(javaMethod, graph); - final InstalledCode installedCode = getBackend().createDefaultInstalledCode(javaMethod, compilationResult); + final InstalledCode installedCode = getBackend().createDefaultInstalledCode(graph.getDebug(), javaMethod, compilationResult); final Monitor monitor = new Monitor(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/RethrowDeoptMaterializeTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/RethrowDeoptMaterializeTest.java new file mode 100644 index 00000000000..a38400057b5 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/RethrowDeoptMaterializeTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + */ +package org.graalvm.compiler.core.test.deopt; + +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.nodes.FrameState; +import org.junit.Test; + +public final class RethrowDeoptMaterializeTest extends GraalCompilerTest { + + private static final Object RETURN_VALUE = "1 2 3"; + private static final RuntimeException DUMMY_EXCEPTION = new RuntimeException(); + + static class MyException extends RuntimeException { + private static final long serialVersionUID = 0L; + + MyException(Throwable cause) { + super(cause); + } + + @SuppressWarnings("sync-override") + @Override + public final Throwable fillInStackTrace() { + return null; + } + } + + public static Object executeDeoptRethrow(int action) { + + try { + if (action != 0) { + throw new MyException(DUMMY_EXCEPTION); + } else if (action == 1) { + throw new MyException(null); + } + } catch (RuntimeException t) { + Throwable e = t.getCause(); + GraalDirectives.deoptimize(); + if (e != DUMMY_EXCEPTION) { + throw t; + } + } + return RETURN_VALUE; + } + + /** + * This tests that a state with {@link FrameState#rethrowException()} set to true can properly + * throw an exception that must be rematerialized. + */ + @Test + public void testDeoptRethrow() { + test("executeDeoptRethrow", 1); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SafepointRethrowDeoptTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SafepointRethrowDeoptTest.java index 6ac8dd399ec..a5fa7f07f8f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SafepointRethrowDeoptTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SafepointRethrowDeoptTest.java @@ -66,7 +66,7 @@ public final class SafepointRethrowDeoptTest extends GraalCompilerTest { @Test public void test() { - Assume.assumeTrue(GraalOptions.GenLoopSafepoints.getValue()); + Assume.assumeTrue(GraalOptions.GenLoopSafepoints.getValue(getInitialOptions())); synchronized (SafepointRethrowDeoptTest.class) { // needs static fields terminate = 1; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SynchronizedMethodDeoptimizationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SynchronizedMethodDeoptimizationTest.java index 50ade26d3c7..bf3d79f830a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SynchronizedMethodDeoptimizationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/deopt/SynchronizedMethodDeoptimizationTest.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.core.test.deopt; +import org.junit.Assume; import org.junit.Test; import org.graalvm.compiler.core.test.GraalCompilerTest; @@ -44,6 +45,9 @@ public class SynchronizedMethodDeoptimizationTest extends GraalCompilerTest { @Test public void test1() { + // https://bugs.openjdk.java.net/browse/JDK-8182755 + Assume.assumeTrue(Java8OrEarlier); + test("testMethodSynchronized", "test"); test("testMethodSynchronized", (Object) null); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/GraphDumpHandler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/CountUppercaseParallelTest.java similarity index 61% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/GraphDumpHandler.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/CountUppercaseParallelTest.java index 4862d4c4c9f..c8a70ec62f9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/GraphDumpHandler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/CountUppercaseParallelTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -20,25 +20,23 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.salver.handler; +package org.graalvm.compiler.core.test.ea; -import java.io.IOException; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.junit.Test; -import org.graalvm.compiler.graph.Graph; -import org.graalvm.compiler.salver.dumper.GraphDumper; - -public class GraphDumpHandler extends AbstractGraalDumpHandler { - - @Override - protected GraphDumper createDumper() { - return new GraphDumper(); +public class CountUppercaseParallelTest extends GraalCompilerTest { + public static long count(CharSequence sentence) { + return sentence.chars().parallel().filter(c -> Character.isUpperCase(c)).count(); } - @Override - public void handle(Object obj, String msg) throws IOException { - if (obj instanceof Graph) { - ensureInitialized(); - dumper.dump((Graph) obj, msg); + @Test + public void testCount() { + String sequence = "In 2017 I would like to run ALL languages in one VM."; + for (int i = 0; i < 5000; i++) { + count(sequence); } + test("count", sequence); } + } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java index 735da745498..f429d53ec52 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java @@ -24,14 +24,8 @@ package org.graalvm.compiler.core.test.ea; import java.util.List; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import org.junit.Assert; - import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; @@ -43,6 +37,10 @@ import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.junit.Assert; + +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.ResolvedJavaMethod; //JaCoCo Exclude @@ -154,16 +152,17 @@ public class EATestBase extends GraalCompilerTest { @SuppressWarnings("try") protected void prepareGraph(String snippet, boolean iterativeEscapeAnalysis) { ResolvedJavaMethod method = getResolvedJavaMethod(snippet); - try (Scope s = Debug.scope(getClass(), method, getCodeCache())) { - graph = parseEager(method, AllowAssumptions.YES); + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope(getClass(), method, getCodeCache())) { + graph = parseEager(method, AllowAssumptions.YES, debug); context = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); new DeadCodeEliminationPhase().apply(graph); new CanonicalizerPhase().apply(graph, context); - new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(), null).apply(graph, context); + new PartialEscapePhase(iterativeEscapeAnalysis, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); returnNodes = graph.getNodes(ReturnNode.TYPE).snapshot(); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java index ebb431f5c3d..3af2ec92d7c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -22,21 +22,26 @@ */ package org.graalvm.compiler.core.test.ea; -import jdk.vm.ci.meta.JavaConstant; - -import org.junit.Assert; -import org.junit.Test; +import java.util.List; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.loop.DefaultLoopPolicies; import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase; import org.graalvm.compiler.loop.phases.LoopPeelingPhase; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.ReturnNode; +import org.graalvm.compiler.nodes.extended.BoxNode; import org.graalvm.compiler.nodes.extended.ValueAnchorNode; +import org.graalvm.compiler.nodes.java.LoadFieldNode; import org.graalvm.compiler.nodes.virtual.AllocatedObjectNode; import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.junit.Assert; +import org.junit.Test; + +import jdk.vm.ci.meta.JavaConstant; /** * The PartialEscapeAnalysisPhase is expected to remove all allocations and return the correct @@ -179,6 +184,50 @@ public class EscapeAnalysisTest extends EATestBase { return obj.x <= 3 ? 1 : 0; } + @Test + public void testMergeAllocationsInt2() { + testEscapeAnalysis("testMergeAllocationsInt2Snippet", JavaConstant.forInt(1), true); + } + + public int testMergeAllocationsInt2Snippet(int a) { + /* + * The initial object in obj exists until the end of the function, but it can still be + * merged with the one allocated in the else block because noone can observe the identity. + */ + TestClassInt obj = new TestClassInt(1, 2); + if (a < 0) { + notInlineable(); + } else { + obj = new TestClassInt(1, 2); + notInlineable(); + } + return obj.x <= 3 ? 1 : 0; + } + + @Test + public void testMergeAllocationsInt3() { + // ensure that the result is not constant: + assertTrue(testMergeAllocationsInt3Snippet(true)); + assertFalse(testMergeAllocationsInt3Snippet(false)); + + prepareGraph("testMergeAllocationsInt3Snippet", true); + assertFalse(graph.getNodes().filter(ReturnNode.class).first().result().isConstant()); + } + + public boolean testMergeAllocationsInt3Snippet(boolean a) { + TestClassInt phi1; + TestClassInt phi2; + if (a) { + field = new TestClassObject(); + field = new TestClassObject(); + phi1 = phi2 = new TestClassInt(1, 2); + } else { + phi1 = new TestClassInt(2, 3); + phi2 = new TestClassInt(3, 4); + } + return phi1 == phi2; + } + @Test public void testMergeAllocationsObj() { testEscapeAnalysis("testMergeAllocationsObjSnippet", JavaConstant.forInt(1), false); @@ -259,9 +308,73 @@ public class EscapeAnalysisTest extends EATestBase { return obj.value <= 3 ? 1 : 0; } + /** + * Tests that a graph with allocations that does not make progress during PEA will not be + * changed. + */ + @Test + public void testChangeHandling() { + prepareGraph("testChangeHandlingSnippet", false); + Assert.assertEquals(2, graph.getNodes().filter(CommitAllocationNode.class).count()); + Assert.assertEquals(1, graph.getNodes().filter(BoxNode.class).count()); + List nodes = graph.getNodes().snapshot(); + // verify that an additional run doesn't add or remove nodes + new PartialEscapePhase(false, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); + Assert.assertEquals(nodes.size(), graph.getNodeCount()); + for (Node node : nodes) { + Assert.assertTrue(node.isAlive()); + } + } + + public volatile Object field; + + public int testChangeHandlingSnippet(int a) { + Object obj; + Integer one = 1; + obj = new MyException(one); + if (a < 0) { + notInlineable(); + } else { + obj = new Integer(1); + notInlineable(); + } + field = obj; + return 1; + } + + /** + * Test the case where allocations before and during a loop that have no usages other than their + * phi need to be recognized as an important change. This needs a loop so that the allocation is + * not trivially removed by dead code elimination. + */ + @Test + public void testRemovalSpecialCase() { + prepareGraph("testRemovalSpecialCaseSnippet", false); + Assert.assertEquals(2, graph.getNodes().filter(CommitAllocationNode.class).count()); + // create the situation by removing the if + graph.replaceFixedWithFloating(graph.getNodes().filter(LoadFieldNode.class).first(), graph.unique(ConstantNode.forInt(0))); + new CanonicalizerPhase().apply(graph, context); + // verify that an additional run removes all allocations + new PartialEscapePhase(false, false, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); + Assert.assertEquals(0, graph.getNodes().filter(CommitAllocationNode.class).count()); + } + + public volatile int field2; + + public int testRemovalSpecialCaseSnippet(int a) { + Object phi = new Object(); + for (int i = 0; i < a; i++) { + field = null; + if (field2 == 1) { + phi = new Object(); + } + } + return phi == null ? 1 : 0; + } + @Test public void testCheckCast() { - testEscapeAnalysis("testCheckCastSnippet", getSnippetReflection().forObject(TestClassObject.class), false); + testEscapeAnalysis("testCheckCastSnippet", getSnippetReflection().forObject(TestClassObject.class), true); } public Object testCheckCastSnippet() { @@ -314,7 +427,7 @@ public class EscapeAnalysisTest extends EATestBase { public void testFullyUnrolledLoop() { prepareGraph("testFullyUnrolledLoopSnippet", false); new LoopFullUnrollPhase(new CanonicalizerPhase(), new DefaultLoopPolicies()).apply(graph, context); - new PartialEscapePhase(false, new CanonicalizerPhase()).apply(graph, context); + new PartialEscapePhase(false, new CanonicalizerPhase(), graph.getOptions()).apply(graph, context); Assert.assertEquals(1, returnNodes.size()); Assert.assertTrue(returnNodes.get(0).result() instanceof AllocatedObjectNode); CommitAllocationNode commit = ((AllocatedObjectNode) returnNodes.get(0).result()).getCommit(); @@ -345,7 +458,7 @@ public class EscapeAnalysisTest extends EATestBase { public void testPeeledLoop() { prepareGraph("testPeeledLoopSnippet", false); new LoopPeelingPhase(new DefaultLoopPolicies()).apply(graph, getDefaultHighTierContext()); - new SchedulePhase().apply(graph); + new SchedulePhase(graph.getOptions()).apply(graph); } public static void testDeoptMonitorSnippetInner(Object o2, Object t, int i) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java index 94ca53834f6..c42c6f001d3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PEAReadEliminationTest.java @@ -28,7 +28,7 @@ import sun.misc.Unsafe; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.java.LoadIndexedNode; import org.graalvm.compiler.nodes.java.StoreIndexedNode; import org.graalvm.compiler.phases.common.CanonicalizerPhase; @@ -130,7 +130,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe1() { StructuredGraph graph = processMethod("testUnsafe1Snippet", false); - assertDeepEquals(1, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(1, graph.getNodes().filter(RawLoadNode.class).count()); } public static int testUnsafe2Snippet(int v, Object array) { @@ -143,7 +143,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe2() { StructuredGraph graph = processMethod("testUnsafe2Snippet", false); - assertDeepEquals(3, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(3, graph.getNodes().filter(RawLoadNode.class).count()); } private static final long offsetObject1 = Unsafe.ARRAY_OBJECT_BASE_OFFSET + Unsafe.ARRAY_OBJECT_INDEX_SCALE * 1; @@ -159,7 +159,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe3() { StructuredGraph graph = processMethod("testUnsafe3Snippet", false); - assertDeepEquals(1, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(1, graph.getNodes().filter(RawLoadNode.class).count()); } public static int testUnsafe4Snippet(int v, Object[] array) { @@ -173,7 +173,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe4() { StructuredGraph graph = processMethod("testUnsafe4Snippet", false); - assertDeepEquals(3, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(3, graph.getNodes().filter(RawLoadNode.class).count()); } private static final long offsetLong1 = Unsafe.ARRAY_LONG_BASE_OFFSET + Unsafe.ARRAY_LONG_INDEX_SCALE * 1; @@ -189,7 +189,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { @Test public void testUnsafe5() { StructuredGraph graph = processMethod("testUnsafe5Snippet", false); - assertDeepEquals(1, graph.getNodes().filter(UnsafeLoadNode.class).count()); + assertDeepEquals(1, graph.getNodes().filter(RawLoadNode.class).count()); } @Override @@ -197,7 +197,7 @@ public class PEAReadEliminationTest extends EarlyReadEliminationTest { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext context = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); - new PartialEscapePhase(false, true, new CanonicalizerPhase(), null).apply(graph, context); + new PartialEscapePhase(false, true, new CanonicalizerPhase(), null, graph.getOptions()).apply(graph, context); return graph; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java index 206ee38c0e4..becd415971a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTest.java @@ -135,6 +135,7 @@ public class PartialEscapeAnalysisTest extends EATestBase { } public static Object[] array = new Object[]{1, 2, 3, 4, 5, "asdf", "asdf"}; + public static char[] charArray = new char[]{1, 2, 3, 4, 5, 'a', 'f'}; public static Object testArrayCopySnippet(int a) { Object[] tmp = new Object[]{a != 1 ? array[a] : null}; @@ -143,6 +144,18 @@ public class PartialEscapeAnalysisTest extends EATestBase { return tmp2[4]; } + @Test + public void testPrimitiveArraycopy() { + testPartialEscapeAnalysis("testPrimitiveArraycopySnippet", 0, 0); + } + + public static Object testPrimitiveArraycopySnippet(int a) { + char[] tmp = new char[]{a != 1 ? charArray[a] : 0}; + char[] tmp2 = new char[5]; + System.arraycopy(tmp, 0, tmp2, 4, 1); + return tmp2[4]; + } + @Test @Ignore public void testCache() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTreesTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTreesTest.java new file mode 100644 index 00000000000..f5580a3bad8 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PartialEscapeAnalysisTreesTest.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test.ea; + +import java.util.HashSet; + +import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.nodes.debug.BlackholeNode; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; +import org.junit.Assert; +import org.junit.Test; + +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +/* + * Test whether complex tree structures properly maintain identity. + */ +public class PartialEscapeAnalysisTreesTest extends EATestBase { + + static class TreeNode { + TreeNode left; + TreeNode right; + + TreeNode() { + + } + + TreeNode(TreeNode left, TreeNode right) { + this.left = left; + this.right = right; + } + + public void visit(HashSet instances) { + instances.add(this); + if (left != null) { + left.visit(instances); + } + if (right != null) { + right.visit(instances); + } + } + + int countInstances() { + HashSet instances = new HashSet<>(); + visit(instances); + return instances.size(); + } + } + + public static TreeNode buildTree(boolean a) { + TreeNode leftChild; + TreeNode rightChild; + TreeNode taskToFork; + TreeNode task; + if (a) { + GraalDirectives.blackhole(new TreeNode()); + leftChild = new TreeNode(); + rightChild = new TreeNode(); + task = new TreeNode(leftChild, rightChild); + taskToFork = rightChild; + GraalDirectives.blackhole(task); + } else { + leftChild = new TreeNode(); + rightChild = new TreeNode(); + task = new TreeNode(leftChild, rightChild); + taskToFork = leftChild; + GraalDirectives.blackhole(task); + } + if (taskToFork.left == null) { + taskToFork.left = new TreeNode(); + } + + return new TreeNode(task, null); + } + + @Test + public void testBuildTree() { + testGraph("buildTree"); + } + + /** + * Prepare a graph that includes some blackholes and then remove the blackholes and compile + * normally to create an unusual situation for PEA. + */ + @SuppressWarnings("try") + public void testGraph(String name) { + ResolvedJavaMethod method = getResolvedJavaMethod(name); + + prepareGraph(name, true); + try (DebugContext.Scope s = graph.getDebug().scope(getClass(), method, getCodeCache(), graph)) { + for (BlackholeNode node : graph.getNodes().filter(BlackholeNode.class)) { + graph.removeFixed(node); + } + new DeadCodeEliminationPhase().apply(graph); + new CanonicalizerPhase().apply(graph, context); + + InstalledCode code = getCode(method, graph, true); + + GraalCompilerTest.Result r = executeExpected(method, null, true); + int expectedInstances = ((TreeNode) r.returnValue).countInstances(); + TreeNode r2 = (TreeNode) code.executeVarargs(true); + Assert.assertEquals("Wrong number of nodes in tree", expectedInstances, r2.countInstances()); + + r = executeExpected(method, null, false); + expectedInstances = ((TreeNode) r.returnValue).countInstances(); + r2 = (TreeNode) code.executeVarargs(false); + Assert.assertEquals("Wrong number of nodes in tree", expectedInstances, r2.countInstances()); + } catch (Throwable e) { + throw graph.getDebug().handle(e); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PoorMansEATest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PoorMansEATest.java index 128ee5a79bc..5d73a474bf8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PoorMansEATest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/PoorMansEATest.java @@ -22,11 +22,8 @@ */ package org.graalvm.compiler.core.test.ea; -import org.junit.Test; - import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.FrameState; @@ -40,6 +37,7 @@ import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.junit.Test; /** * Tests {@link AbstractNewObjectNode#simplify(org.graalvm.compiler.graph.spi.SimplifierTool)}. @@ -63,7 +61,8 @@ public class PoorMansEATest extends GraalCompilerTest { @SuppressWarnings("try") private void test(final String snippet) { - try (Scope s = Debug.scope("PoorMansEATest", new DebugDumpScope(snippet))) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("PoorMansEATest", new DebugDumpScope(snippet))) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); HighTierContext highTierContext = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, highTierContext); @@ -82,7 +81,7 @@ public class PoorMansEATest extends GraalCompilerTest { } new CanonicalizerPhase().apply(graph, context); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.java index fbfbd64b690..e54bea3a626 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.java @@ -38,6 +38,10 @@ public class UnsafeEATest extends EATestBase { private static final long fieldOffset1; private static final long fieldOffset2; + private static final long byteArrayBaseOffset; + private static final long intArrayBaseOffset; + private static final long longArrayBaseOffset; + static { try { long localFieldOffset1 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("x")); @@ -51,6 +55,9 @@ public class UnsafeEATest extends EATestBase { fieldOffset2 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("z")); } assert fieldOffset2 == fieldOffset1 + 4; + byteArrayBaseOffset = UNSAFE.arrayBaseOffset(byte[].class); + intArrayBaseOffset = UNSAFE.arrayBaseOffset(int[].class); + longArrayBaseOffset = UNSAFE.arrayBaseOffset(long[].class); } catch (Exception e) { throw new RuntimeException(e); } @@ -195,4 +202,77 @@ public class UnsafeEATest extends EATestBase { } return x; } + + public static int testWriteIntToByteArraySnippet() { + byte[] array = new byte[4]; + UNSAFE.putInt(array, byteArrayBaseOffset, 0x01020304); + return array[0]; + } + + @Test + public void testWriteIntToByteArray() { + test("testWriteIntToByteArraySnippet"); + } + + public static byte testWriteSignedExtendedByteToByteArraySnippet(byte b) { + byte[] array = new byte[4]; + array[0] = 0x01; + array[1] = 0x02; + array[2] = 0x03; + array[3] = 0x04; + UNSAFE.putInt(array, byteArrayBaseOffset, b); + return array[3]; + } + + @Test + public void testWriteSignedExtendedByteToByteArray() { + test("testWriteSignedExtendedByteToByteArraySnippet", (byte) 0); + } + + public static int testWriteLongToIntArraySnippet() { + int[] array = new int[2]; + UNSAFE.putLong(array, intArrayBaseOffset, 0x0102030405060708L); + return array[0]; + } + + @Test + public void testWriteLongToIntArray() { + test("testWriteLongToIntArraySnippet"); + } + + public static int testWriteByteToIntArraySnippet() { + int[] array = new int[1]; + array[0] = 0x01020304; + UNSAFE.putByte(array, intArrayBaseOffset, (byte) 0x05); + return array[0]; + } + + @Test + public void testWriteByteToIntArray() { + test("testWriteByteToIntArraySnippet"); + } + + public static long testWriteIntToLongArraySnippet() { + long[] array = new long[1]; + array[0] = 0x0102030405060708L; + UNSAFE.putInt(array, longArrayBaseOffset, 0x04030201); + return array[0]; + } + + @Test + public void testWriteIntToLongArray() { + test("testWriteIntToLongArraySnippet"); + } + + public static float testWriteFloatToIntArraySnippet() { + float[] array = new float[1]; + UNSAFE.putInt(array, intArrayBaseOffset, Float.floatToRawIntBits(0.5f)); + return array[0]; + } + + @Test + public void testWriteFloatToIntArray() { + test("testWriteFloatToIntArraySnippet"); + } + } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java index 2c558b1d247..7d6e97b23a4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java @@ -22,21 +22,15 @@ */ package org.graalvm.compiler.core.test.inlining; -import jdk.vm.ci.code.site.InfopointReason; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import org.junit.Ignore; -import org.junit.Test; - import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.FullInfopointNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.StructuredGraph.Builder; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; @@ -44,6 +38,11 @@ import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Ignore; +import org.junit.Test; + +import jdk.vm.ci.code.site.InfopointReason; +import jdk.vm.ci.meta.ResolvedJavaMethod; public class InliningTest extends GraalCompilerTest { @@ -236,24 +235,26 @@ public class InliningTest extends GraalCompilerTest { @SuppressWarnings("try") private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) { - try (Scope s = Debug.scope("InliningTest", new DebugDumpScope(snippet, true))) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("InliningTest", new DebugDumpScope(snippet, true))) { ResolvedJavaMethod method = getResolvedJavaMethod(snippet); - StructuredGraph graph = eagerInfopointMode ? parseDebug(method, AllowAssumptions.YES) : parseEager(method, AllowAssumptions.YES); - try (Scope s2 = Debug.scope("Inlining", graph)) { + Builder builder = builder(method, AllowAssumptions.YES, debug); + StructuredGraph graph = eagerInfopointMode ? parse(builder, getDebugGraphBuilderSuite()) : parse(builder, getEagerGraphBuilderSuite()); + try (DebugContext.Scope s2 = debug.scope("Inlining", graph)) { PhaseSuite graphBuilderSuite = eagerInfopointMode ? getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withFullInfopoints(true)) : getDefaultGraphBuilderSuite(); HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, context); new InliningPhase(new CanonicalizerPhase()).apply(graph, context); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "Graph"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph"); new CanonicalizerPhase().apply(graph, context); new DeadCodeEliminationPhase().apply(graph); return graph; } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java new file mode 100644 index 00000000000..10505f2de92 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core.test.inlining; + +import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.TTY; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.nodes.Invoke; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.java.MethodCallTargetNode; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.BasePhase; +import org.graalvm.compiler.phases.OptimisticOptimizations; +import org.graalvm.compiler.phases.PhaseSuite; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; +import org.graalvm.compiler.phases.common.inlining.InliningUtil; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; +import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; +import org.graalvm.util.EconomicSet; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; +import sun.misc.Unsafe; + +public class NestedLoopEffectsPhaseComplexityTest extends GraalCompilerTest { + + public static int IntSideEffect; + public static int[] Memory = new int[]{0}; + + public static void recursiveLoopMethodUnsafeLoad(int a) { + if (UNSAFE.getInt(Memory, (long) Unsafe.ARRAY_INT_BASE_OFFSET) == 0) { + return; + } + for (int i = 0; i < a; i++) { + recursiveLoopMethodUnsafeLoad(i); + } + } + + public static void recursiveLoopMethodFieldLoad(int a) { + if (IntSideEffect == 0) { + return; + } + for (int i = 0; i < a; i++) { + recursiveLoopMethodFieldLoad(i); + } + } + + public static void recursiveLoopMethod(int a) { + if (a == 0) { + return; + } + for (int i = 0; i < a; i++) { + recursiveLoopMethod(i); + } + } + + private static final boolean LOG_PHASE_TIMINGS = false; + private static int InliningCountLowerBound = 1; + private static int InliningCountUpperBound = 32; + + @Test(timeout = 120_000) + public void inlineDirectRecursiveLoopCallUnsafeLoad() { + testAndTime("recursiveLoopMethodUnsafeLoad"); + } + + @Test(timeout = 120_000) + public void inlineDirectRecursiveLoopCallFieldLoad() { + testAndTime("recursiveLoopMethodFieldLoad"); + } + + @Test(timeout = 120_000) + public void inlineDirectRecursiveLoopCallNoReads() { + testAndTime("recursiveLoopMethod"); + } + + private void testAndTime(String snippet) { + for (int i = InliningCountLowerBound; i < InliningCountUpperBound; i++) { + StructuredGraph g1 = prepareGraph(snippet, i); + StructuredGraph g2 = (StructuredGraph) g1.copy(g1.getDebug()); + ResolvedJavaMethod method = g1.method(); + long elapsedRE = runAndTimePhase(g1, new EarlyReadEliminationPhase(new CanonicalizerPhase())); + long elapsedPEA = runAndTimePhase(g2, new PartialEscapePhase(true, new CanonicalizerPhase(), g1.getOptions())); + if (LOG_PHASE_TIMINGS) { + TTY.printf("Needed %dms to run early partial escape analysis on a graph with %d nested loops compiling method %s\n", elapsedPEA, i, method); + } + if (LOG_PHASE_TIMINGS) { + TTY.printf("Needed %dms to run early read elimination on a graph with %d nested loops compiling method %s\n", elapsedRE, i, method); + } + } + } + + private long runAndTimePhase(StructuredGraph g, BasePhase phase) { + HighTierContext context = getDefaultHighTierContext(); + long start = System.currentTimeMillis(); + phase.apply(g, context); + long end = System.currentTimeMillis(); + DebugContext debug = g.getDebug(); + debug.dump(DebugContext.DETAILED_LEVEL, g, "After %s", phase.contractorName()); + return end - start; + } + + private StructuredGraph prepareGraph(String snippet, int inliningCount) { + ResolvedJavaMethod callerMethod = getResolvedJavaMethod(snippet); + StructuredGraph callerGraph = parseEager(callerMethod, AllowAssumptions.YES); + PhaseSuite graphBuilderSuite = getDefaultGraphBuilderSuite(); + HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + Invoke next = callerGraph.getNodes(MethodCallTargetNode.TYPE).first().invoke(); + StructuredGraph calleeGraph = parseBytecodes(next.callTarget().targetMethod(), context, canonicalizer); + ResolvedJavaMethod calleeMethod = next.callTarget().targetMethod(); + for (int i = 0; i < inliningCount; i++) { + next = callerGraph.getNodes(MethodCallTargetNode.TYPE).first().invoke(); + EconomicSet canonicalizeNodes = InliningUtil.inlineForCanonicalization(next, calleeGraph, false, calleeMethod); + canonicalizer.applyIncremental(callerGraph, context, canonicalizeNodes); + callerGraph.getDebug().dump(DebugContext.DETAILED_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i); + } + return callerGraph; + } + + private StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer) { + OptionValues options = getInitialOptions(); + StructuredGraph newGraph = new StructuredGraph.Builder(options, getDebugContext(options), AllowAssumptions.NO).method(method).build(); + context.getGraphBuilderSuite().apply(newGraph, context); + new DeadCodeEliminationPhase(Optional).apply(newGraph); + canonicalizer.apply(newGraph, context); + return newGraph; + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/RecursiveInliningTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/RecursiveInliningTest.java deleted file mode 100644 index 4e1d784d4a4..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/RecursiveInliningTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core.test.inlining; - -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; -import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; - -import org.junit.Test; - -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.DebugDumpScope; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.nodes.InvokeNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; -import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.PhaseSuite; -import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; -import org.graalvm.compiler.phases.common.inlining.InliningUtil; -import org.graalvm.compiler.phases.schedule.SchedulePhase; -import org.graalvm.compiler.phases.tiers.HighTierContext; -import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; -import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; - -import jdk.vm.ci.meta.ResolvedJavaMethod; -import sun.misc.Unsafe; - -public class RecursiveInliningTest extends GraalCompilerTest { - - public static int SideEffectI; - public static int[] Memory = new int[]{1, 2}; - - public static final Unsafe UNSAFE; - static { - try { - Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); - theUnsafe.setAccessible(true); - UNSAFE = (Unsafe) theUnsafe.get(Unsafe.class); - } catch (Exception e) { - throw new RuntimeException("Exception while trying to get Unsafe", e); - } - } - - public static void recursiveLoopMethodUnsafeLoad(int a) { - if (UNSAFE.getInt(Memory, (long) Unsafe.ARRAY_LONG_BASE_OFFSET) == 0) { - return; - } - for (int i = 0; i < a; i++) { - recursiveLoopMethodUnsafeLoad(i); - } - } - - public static void recursiveLoopMethodFieldLoad(int a) { - if (SideEffectI == 0) { - return; - } - for (int i = 0; i < a; i++) { - recursiveLoopMethodFieldLoad(i); - } - } - - public static void recursiveLoopMethod(int a) { - if (a == 0) { - return; - } - for (int i = 0; i < a; i++) { - recursiveLoopMethod(i); - } - } - - public static final boolean LOG = false; - - public static int IterationsStart = 1; - public static int IterationsEnd = 128; - - @Test(timeout = 120_000) - public void inlineDirectRecursiveLoopCallUnsafeLoad() { - testAndTime("recursiveLoopMethodUnsafeLoad"); - } - - @Test(timeout = 120_000) - public void inlineDirectRecursiveLoopCallFieldLoad() { - testAndTime("recursiveLoopMethodFieldLoad"); - } - - @Test(timeout = 120_000) - public void inlineDirectRecursiveLoopCallNoReads() { - testAndTime("recursiveLoopMethod"); - } - - private void testAndTime(String snippet) { - for (int i = IterationsStart; i < IterationsEnd; i++) { - StructuredGraph graph = getGraph(snippet, i); - long elapsed = runAndTimeEarlyReadEliminationPhase(graph); - if (LOG) { - System.out.printf("Needed %dms to run early read elimination on a graph with %d recursive inlined calls of method %s\n", elapsed, i, graph.method()); - } - } - for (int i = IterationsStart; i < IterationsEnd; i++) { - StructuredGraph graph = getGraph(snippet, i); - long elapsed = runAndTimePartialEscapeAnalysis(graph); - if (LOG) { - System.out.printf("Needed %dms to run early partial escape analysis on a graph with %d recursive inlined calls of method %s\n", elapsed, i, graph.method()); - } - } - } - - private long runAndTimePartialEscapeAnalysis(StructuredGraph g) { - PartialEscapePhase p = new PartialEscapePhase(true, new CanonicalizerPhase()); - HighTierContext context = getDefaultHighTierContext(); - long start = System.currentTimeMillis(); - p.apply(g, context); - long end = System.currentTimeMillis(); - Debug.dump(Debug.BASIC_LOG_LEVEL, g, "After PEA"); - return end - start; - } - - private long runAndTimeEarlyReadEliminationPhase(StructuredGraph g) { - EarlyReadEliminationPhase er = new EarlyReadEliminationPhase(new CanonicalizerPhase()); - HighTierContext context = getDefaultHighTierContext(); - long start = System.currentTimeMillis(); - er.apply(g, context); - long end = System.currentTimeMillis(); - Debug.dump(Debug.BASIC_LOG_LEVEL, g, "After Early Read Elimination"); - return end - start; - } - - @SuppressWarnings("try") - private StructuredGraph getGraph(final String snippet, int nrOfInlinings) { - try (Scope s = Debug.scope("RecursiveInliningTest", new DebugDumpScope(snippet, true))) { - ResolvedJavaMethod callerMethod = getResolvedJavaMethod(snippet); - StructuredGraph callerGraph = parseEager(callerMethod, AllowAssumptions.YES); - PhaseSuite graphBuilderSuite = getDefaultGraphBuilderSuite(); - HighTierContext context = new HighTierContext(getProviders(), graphBuilderSuite, OptimisticOptimizations.ALL); - CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - - for (int i = 0; i < nrOfInlinings; i++) { - InvokeNode next = getNextInvoke(callerGraph); - ResolvedJavaMethod calleeMethod = next.callTarget().targetMethod(); - StructuredGraph calleeGraph = getInlineeGraph(next, callerGraph, context, canonicalizer); - List canonicalizeNodes = new ArrayList<>(); - InliningUtil.inline(next, calleeGraph, false, canonicalizeNodes, calleeMethod); - canonicalizer.applyIncremental(callerGraph, context, canonicalizeNodes); - Debug.dump(Debug.BASIC_LOG_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i); - } - new SchedulePhase().apply(callerGraph); - return callerGraph; - } catch (Throwable e) { - throw Debug.handle(e); - } - } - - private static StructuredGraph getInlineeGraph(InvokeNode invoke, StructuredGraph caller, HighTierContext context, CanonicalizerPhase canonicalizer) { - StructuredGraph result = InliningUtil.getIntrinsicGraph(context.getReplacements(), invoke.callTarget().targetMethod(), invoke.bci()); - if (result != null) { - return result; - } - return parseBytecodes(invoke.callTarget().targetMethod(), context, canonicalizer, caller); - } - - @SuppressWarnings("try") - private static StructuredGraph parseBytecodes(ResolvedJavaMethod method, HighTierContext context, CanonicalizerPhase canonicalizer, StructuredGraph caller) { - StructuredGraph newGraph = new StructuredGraph(method, AllowAssumptions.from(caller.getAssumptions() != null), INVALID_COMPILATION_ID); - if (!caller.isUnsafeAccessTrackingEnabled()) { - newGraph.disableUnsafeAccessTracking(); - } - if (context.getGraphBuilderSuite() != null) { - context.getGraphBuilderSuite().apply(newGraph, context); - } - assert newGraph.start().next() != null : "graph needs to be populated by the GraphBuilderSuite " + method + ", " + method.canBeInlined(); - new DeadCodeEliminationPhase(Optional).apply(newGraph); - canonicalizer.apply(newGraph, context); - return newGraph; - } - - private static InvokeNode getNextInvoke(StructuredGraph graph) { - return graph.getNodes().filter(InvokeNode.class).first(); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/GraalTutorial.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/GraalTutorial.java index 815bb88a54a..7e7c166e81e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/GraalTutorial.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/GraalTutorial.java @@ -22,13 +22,13 @@ */ package org.graalvm.compiler.core.test.tutorial; +import java.lang.reflect.Method; +import java.util.regex.Pattern; + +import org.graalvm.compiler.bytecode.BytecodeDisassembler; import org.junit.Assert; import org.junit.Test; -import org.graalvm.compiler.bytecode.Bytecode; -import org.graalvm.compiler.bytecode.BytecodeDisassembler; -import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; - import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.InvalidInstalledCodeException; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -49,14 +49,31 @@ public class GraalTutorial extends InvokeGraal { */ @Test - public void testPrintBytecodes() { - ResolvedJavaMethod method = findMethod(String.class, "hashCode"); - Bytecode bytecode = new ResolvedJavaMethodBytecode(method); + public void testGetBytecodes() throws NoSuchMethodException { + Method reflectionMethod = String.class.getDeclaredMethod("hashCode"); + ResolvedJavaMethod method = metaAccess.lookupJavaMethod(reflectionMethod); - byte[] bytecodes = bytecode.getCode(); - Assert.assertNotNull(bytecodes); + /* + * ResolvedJavaMethod provides all information that you want about a method, for example, + * the bytecodes. + */ + byte[] bytecodes = method.getCode(); - System.out.println(new BytecodeDisassembler().disassemble(bytecode)); + /* + * BytecodeDisassembler shows you how to iterate bytecodes, how to access type information, + * and more. + */ + String disassembly = new BytecodeDisassembler().disassemble(method); + + /* + * We don't want test cases to print any output, so we check the validity of the output + * instead. + */ + Pattern disassemblyLineRE = Pattern.compile(" *\\d+: [a-z][\\w_]+"); + for (String line : disassembly.split("\\n")) { + Assert.assertTrue(line, disassemblyLineRE.matcher(line).find()); + } + Assert.assertTrue(bytecodes.length > 0); } /* @@ -131,6 +148,21 @@ public class GraalTutorial extends InvokeGraal { * Tutorial example for snippets and lowering. */ + public static int identityHashCodeUsage(Object obj) { + return System.identityHashCode(obj); + } + + @Test + public void testIdentityHashCodeUsage() throws InvalidInstalledCodeException { + Object a = new Object(); + int expectedResult = identityHashCodeUsage(a); + + InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "identityHashCodeUsage")); + + int result = (int) compiledMethod.executeVarargs(a); + Assert.assertEquals(expectedResult, result); + } + static class A { } @@ -173,17 +205,18 @@ public class GraalTutorial extends InvokeGraal { * Tutorial example for intrinsic methods. */ - public static double intrinsicUsage(double val) { - return Math.sin(val); + public static int intrinsicIntegerReverseBytes(int val) { + return Integer.reverseBytes(val); } @Test - public void testIntrinsicUsage() throws InvalidInstalledCodeException { - double expectedResult = intrinsicUsage(42d); + public void testIntrinsicIntegerReverseBytes() throws InvalidInstalledCodeException { + int input = 0x12345678; + int expected = intrinsicIntegerReverseBytes(input); - InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "intrinsicUsage")); + InstalledCode compiledMethod = compileAndInstallMethod(findMethod(GraalTutorial.class, "intrinsicIntegerReverseBytes")); - double result = (double) compiledMethod.executeVarargs(42d); - Assert.assertEquals(expectedResult, result, 0); + int actual = (int) compiledMethod.executeVarargs(input); + Assert.assertEquals(expected, actual); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java index c722047e256..60a28e30b0a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/InvokeGraal.java @@ -23,6 +23,7 @@ package org.graalvm.compiler.core.test.tutorial; import static org.graalvm.compiler.core.common.CompilationRequestIdentifier.asCompilationRequest; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.lang.reflect.Method; @@ -31,13 +32,14 @@ import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.GraalCompiler; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -83,7 +85,9 @@ public class InvokeGraal { protected InstalledCode compileAndInstallMethod(ResolvedJavaMethod method) { /* Create a unique compilation identifier, visible in IGV. */ CompilationIdentifier compilationId = backend.getCompilationIdentifier(method); - try (Scope s = Debug.scope("compileAndInstallMethod", new DebugDumpScope(String.valueOf(compilationId), true))) { + OptionValues options = getInitialOptions(); + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); + try (DebugContext.Scope s = debug.scope("compileAndInstallMethod", new DebugDumpScope(String.valueOf(compilationId), true))) { /* * The graph that is compiled. We leave it empty (no nodes added yet). This means that @@ -91,7 +95,7 @@ public class InvokeGraal { * that we want the compilation to make optimistic assumptions about runtime state such * as the loaded class hierarchy. */ - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.YES, compilationId); + StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).method(method).compilationId(compilationId).build(); /* * The phases used to build the graph. Usually this is just the GraphBuilderPhase. If @@ -103,12 +107,12 @@ public class InvokeGraal { * The optimization phases that are applied to the graph. This is the main configuration * point for Graal. Add or remove phases to customize your compilation. */ - Suites suites = backend.getSuites().getDefaultSuites(); + Suites suites = backend.getSuites().getDefaultSuites(options); /* * The low-level phases that are applied to the low-level representation. */ - LIRSuites lirSuites = backend.getSuites().getDefaultLIRSuites(); + LIRSuites lirSuites = backend.getSuites().getDefaultLIRSuites(options); /* * We want Graal to perform all speculative optimistic optimizations, using the @@ -129,9 +133,9 @@ public class InvokeGraal { * Install the compilation result into the VM, i.e., copy the byte[] array that contains * the machine code into an actual executable memory location. */ - return backend.addInstalledCode(method, asCompilationRequest(compilationId), compilationResult); + return backend.addInstalledCode(debug, method, asCompilationRequest(compilationId), compilationResult); } catch (Throwable ex) { - throw Debug.handle(ex); + throw debug.handle(ex); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java index 4f8a61e1901..1b7f0d1327c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.test.tutorial; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; +import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions; import java.util.ArrayDeque; import java.util.Collections; @@ -32,9 +32,9 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.debug.Debug.Scope; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.java.GraphBuilderPhase; @@ -45,7 +45,6 @@ import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; @@ -59,6 +58,7 @@ import org.graalvm.compiler.nodes.java.NewInstanceNode; import org.graalvm.compiler.nodes.java.StoreFieldNode; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.graph.StatelessPostOrderNodeIterator; @@ -241,12 +241,14 @@ public class StaticAnalysis { * Build the Graal graph for the method using the bytecode parser provided by Graal. */ - StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, INVALID_COMPILATION_ID); + OptionValues options = getInitialOptions(); + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build(); /* * Support for graph dumping, IGV uses this information to show the method name of a * graph. */ - try (Scope scope = Debug.scope("graph building", graph)) { + try (DebugContext.Scope scope = debug.scope("graph building", graph)) { /* * We want all types to be resolved by the graph builder, i.e., we want classes * referenced by the bytecodes to be loaded and initialized. Since we do not run @@ -272,7 +274,7 @@ public class StaticAnalysis { GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(metaAccess, stampProvider, null, null, graphBuilderConfig, optimisticOpts, null); graphBuilder.apply(graph); } catch (Throwable ex) { - Debug.handle(ex); + debug.handle(ex); } /* diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationPrinter.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationPrinter.java new file mode 100644 index 00000000000..0697def7112 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationPrinter.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core; + +import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation; + +import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.debug.Management; +import org.graalvm.compiler.debug.TTY; +import org.graalvm.compiler.options.OptionValues; + +import jdk.vm.ci.meta.JavaMethod; +import jdk.vm.ci.runtime.JVMCICompiler; + +/** + * Utility for printing an informational line to {@link TTY} upon completion of compiling a method. + */ +public final class CompilationPrinter { + + private final CompilationIdentifier id; + private final JavaMethod method; + private final int entryBCI; + private final long start; + private final long allocatedBytesBefore; + + /** + * Gets an object that will report statistics for a compilation if + * {@link GraalCompilerOptions#PrintCompilation} is enabled and {@link TTY} is not suppressed. + * This method should be called just before a compilation starts as it captures pre-compilation + * data for the purpose of {@linkplain #finish(CompilationResult) printing} the post-compilation + * statistics. + * + * @param options used to get the value of {@link GraalCompilerOptions#PrintCompilation} + * @param id the identifier for the compilation + * @param method the method for which code is being compiled + * @param entryBCI the BCI at which compilation starts + */ + public static CompilationPrinter begin(OptionValues options, CompilationIdentifier id, JavaMethod method, int entryBCI) { + if (PrintCompilation.getValue(options) && !TTY.isSuppressed()) { + return new CompilationPrinter(id, method, entryBCI); + } + return DISABLED; + } + + private static final CompilationPrinter DISABLED = new CompilationPrinter(); + + private CompilationPrinter() { + this.method = null; + this.id = null; + this.entryBCI = -1; + this.start = -1; + this.allocatedBytesBefore = -1; + } + + private CompilationPrinter(CompilationIdentifier id, JavaMethod method, int entryBCI) { + this.method = method; + this.id = id; + this.entryBCI = entryBCI; + + final long threadId = Thread.currentThread().getId(); + start = System.nanoTime(); + allocatedBytesBefore = getAllocatedBytes(threadId); + } + + private String getMethodDescription() { + return String.format("%-30s %-70s %-45s %-50s %s", id.toString(CompilationIdentifier.Verbosity.ID), + method.getDeclaringClass().getName(), method.getName(), + method.getSignature().toMethodDescriptor(), + entryBCI == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") "); + } + + /** + * Notifies this object that the compilation finished and the informational line should be + * printed to {@link TTY}. + */ + public void finish(CompilationResult result) { + if (id != null) { + final long threadId = Thread.currentThread().getId(); + final long stop = System.nanoTime(); + final long duration = (stop - start) / 1000000; + final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1; + final int bytecodeSize = result != null ? result.getBytecodeSize() : 0; + final long allocatedBytesAfter = getAllocatedBytes(threadId); + final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024; + + TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); + } + } + + static com.sun.management.ThreadMXBean threadMXBean; + + static long getAllocatedBytes(long threadId) { + if (threadMXBean == null) { + threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean(); + } + return threadMXBean.getThreadAllocatedBytes(threadId); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java new file mode 100644 index 00000000000..0f46ca098d9 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.core; + +import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM; +import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction; +import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction; +import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException; +import static org.graalvm.compiler.core.GraalCompilerOptions.MaxCompilationProblemsPerAction; +import static org.graalvm.compiler.debug.DebugContext.VERBOSE_LEVEL; +import static org.graalvm.compiler.debug.DebugOptions.Dump; +import static org.graalvm.compiler.debug.DebugOptions.DumpPath; +import static org.graalvm.compiler.debug.DebugOptions.MethodFilter; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.Map; + +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DiagnosticsOutputDirectory; +import org.graalvm.compiler.debug.PathUtilities; +import org.graalvm.compiler.debug.TTY; +import org.graalvm.compiler.options.EnumOptionKey; +import org.graalvm.compiler.options.OptionValues; + +import jdk.vm.ci.code.BailoutException; + +/** + * Wrapper for a compilation that centralizes what action to take based on + * {@link GraalCompilerOptions#CompilationBailoutAction} and + * {@link GraalCompilerOptions#CompilationFailureAction} when an uncaught exception occurs during + * compilation. + */ +public abstract class CompilationWrapper { + + /** + * Actions to take upon an exception being raised during compilation performed via + * {@link CompilationWrapper}. The actions are with respect to what the user sees on the + * console. The compilation requester determines what ultimate action is taken in + * {@link CompilationWrapper#handleException(Throwable)}. + * + * The actions are in ascending order of verbosity. + */ + public enum ExceptionAction { + /** + * Print nothing to the console. + */ + Silent, + /** + * Print a stack trace to the console. + */ + Print, + /** + * An exception causes the compilation to be retried with extra diagnostics enabled. + */ + Diagnose, + /** + * Same as {@link #Diagnose} except that the VM process is exited after retrying. + */ + ExitVM; + + static ValueHelp HELP = new ValueHelp(); + + static class ValueHelp implements EnumOptionKey.ValueHelp { + @Override + public String getHelp(Object value) { + ExceptionAction action = (ExceptionAction) value; + switch (action) { + case Silent: + return action + ": Print nothing to the console."; + case Print: + return action + ": Print a stack trace to the console."; + case Diagnose: + return action + ": Retry the compilation with extra diagnostics."; + case ExitVM: + return action + ": Same as " + Diagnose + " except that the VM process exits after retrying."; + } + return null; + } + } + + /** + * Gets the action that is one level less verbose than this action, bottoming out at the + * least verbose action. + */ + ExceptionAction quieter() { + assert ExceptionAction.Silent.ordinal() == 0; + int index = Math.max(ordinal() - 1, 0); + return values()[index]; + } + } + + private final DiagnosticsOutputDirectory outputDirectory; + + private final Map problemsHandledPerAction; + + /** + * @param outputDirectory object used to access a directory for dumping if the compilation is + * re-executed + * @param problemsHandledPerAction map used to count the number of compilation failures or + * bailouts handled by each action. This is provided by the caller as it is expected + * to be shared between instances of {@link CompilationWrapper}. + */ + public CompilationWrapper(DiagnosticsOutputDirectory outputDirectory, Map problemsHandledPerAction) { + this.outputDirectory = outputDirectory; + this.problemsHandledPerAction = problemsHandledPerAction; + } + + /** + * Handles an uncaught exception. + * + * @param t an exception thrown during {@link #run(DebugContext)} + * @return a value representing the result of a failed compilation (may be {@code null}) + */ + protected abstract T handleException(Throwable t); + + /** + * Gets the action to take based on the value of {@code actionKey} in {@code options}. + * + * Subclasses can override this to choose a different action based on factors such as whether + * {@code actionKey} has been explicitly set in {@code options} for example. + */ + protected ExceptionAction lookupAction(OptionValues options, EnumOptionKey actionKey) { + if (actionKey == CompilationFailureAction) { + if (ExitVMOnException.getValue(options)) { + assert CompilationFailureAction.getDefaultValue() != ExceptionAction.ExitVM; + assert ExitVMOnException.getDefaultValue() != true; + if (CompilationFailureAction.hasBeenSet(options) && CompilationFailureAction.getValue(options) != ExceptionAction.ExitVM) { + TTY.printf("WARNING: Ignoring %s=%s since %s=true has been explicitly specified.%n", + CompilationFailureAction.getName(), CompilationFailureAction.getValue(options), + ExitVMOnException.getName()); + } + return ExceptionAction.ExitVM; + } + } + return actionKey.getValue(options); + } + + /** + * Perform the compilation wrapped by this object. + * + * @param debug the debug context to use for the compilation + */ + protected abstract T performCompilation(DebugContext debug); + + /** + * Gets a value that represents the input to the compilation. + */ + @Override + public abstract String toString(); + + /** + * Creates the {@link DebugContext} to use when retrying a compilation. + * + * @param options the options for configuring the debug context + */ + protected abstract DebugContext createRetryDebugContext(OptionValues options); + + @SuppressWarnings("try") + public final T run(DebugContext initialDebug) { + try { + return performCompilation(initialDebug); + } catch (Throwable cause) { + OptionValues initialOptions = initialDebug.getOptions(); + + String causeType = "failure"; + EnumOptionKey actionKey; + if (cause instanceof BailoutException) { + actionKey = CompilationBailoutAction; + causeType = "bailout"; + } else { + actionKey = CompilationFailureAction; + causeType = "failure"; + } + ExceptionAction action = lookupAction(initialOptions, actionKey); + + action = adjustAction(initialOptions, actionKey, action); + + if (action == ExceptionAction.Silent) { + return handleException(cause); + } + + if (action == ExceptionAction.Print) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (PrintStream ps = new PrintStream(baos)) { + ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this); + cause.printStackTrace(ps); + ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n", + causeType, + actionKey.getName(), ExceptionAction.Silent, + actionKey.getName(), ExceptionAction.Silent); + ps.printf("To capture more information for diagnosing or reporting a compilation %s, " + + "set %s to %s or %s (e.g., -Dgraal.%s=%s).%n", + causeType, + actionKey.getName(), ExceptionAction.Diagnose, + ExceptionAction.ExitVM, + actionKey.getName(), ExceptionAction.Diagnose); + } + synchronized (CompilationFailureAction) { + // Synchronize to prevent compilation exception + // messages from interleaving. + TTY.println(baos.toString()); + } + return handleException(cause); + } + + // action is Diagnose or ExitVM + + if (Dump.hasBeenSet(initialOptions)) { + // If dumping is explicitly enabled, Graal is being debugged + // so don't interfere with what the user is expecting to see. + return handleException(cause); + } + + String dir = this.outputDirectory.getPath(); + if (dir == null) { + return handleException(cause); + } + String dumpName = PathUtilities.sanitizeFileName(toString()); + File dumpPath = new File(dir, dumpName); + dumpPath.mkdirs(); + if (!dumpPath.exists()) { + TTY.println("Warning: could not create diagnostics directory " + dumpPath); + return handleException(cause); + } + + String message; + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try (PrintStream ps = new PrintStream(baos)) { + ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this); + cause.printStackTrace(ps); + ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n", + causeType, + actionKey.getName(), ExceptionAction.Silent, + actionKey.getName(), ExceptionAction.Silent); + ps.printf("To print a message for a compilation %s without retrying the compilation, " + + "set %s to %s (e.g., -Dgraal.%s=%s).%n", + causeType, + actionKey.getName(), ExceptionAction.Print, + actionKey.getName(), ExceptionAction.Print); + ps.println("Retrying compilation of " + this); + message = baos.toString(); + } + + synchronized (CompilationFailureAction) { + // Synchronize here to serialize retry compilations. This + // mitigates retry compilation storms. + TTY.println(message); + File retryLogFile = new File(dumpPath, "retry.log"); + try (PrintStream ps = new PrintStream(new FileOutputStream(retryLogFile))) { + ps.print(message); + } catch (IOException ioe) { + TTY.printf("Error writing to %s: %s%n", retryLogFile, ioe); + } + + OptionValues retryOptions = new OptionValues(initialOptions, + Dump, ":" + VERBOSE_LEVEL, + MethodFilter, null, + DumpPath, dumpPath.getPath()); + + try (DebugContext retryDebug = createRetryDebugContext(retryOptions)) { + return performCompilation(retryDebug); + } catch (Throwable ignore) { + // Failures during retry are silent + return handleException(cause); + } finally { + if (action == ExitVM) { + synchronized (ExceptionAction.class) { + TTY.println("Exiting VM after retry compilation of " + this); + System.exit(-1); + } + } + } + } + } + } + + /** + * Adjusts {@code initialAction} if necessary based on + * {@link GraalCompilerOptions#MaxCompilationProblemsPerAction}. + */ + private ExceptionAction adjustAction(OptionValues initialOptions, EnumOptionKey actionKey, ExceptionAction initialAction) { + ExceptionAction action = initialAction; + int maxProblems = MaxCompilationProblemsPerAction.getValue(initialOptions); + synchronized (problemsHandledPerAction) { + while (action != ExceptionAction.Silent) { + int problems = problemsHandledPerAction.getOrDefault(action, 0); + if (problems >= maxProblems) { + if (problems == maxProblems) { + TTY.printf("Warning: adjusting %s from %s to %s after %s (%d) failed compilations%n", actionKey, action, action.quieter(), + MaxCompilationProblemsPerAction, maxProblems); + // Ensure that the message above is only printed once + problemsHandledPerAction.put(action, problems + 1); + } + action = action.quieter(); + } else { + break; + } + } + problemsHandledPerAction.put(action, problemsHandledPerAction.getOrDefault(action, 0) + 1); + } + return action; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilerThread.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilerThread.java index 00600db5fc6..645fd7ee758 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilerThread.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilerThread.java @@ -22,42 +22,21 @@ */ package org.graalvm.compiler.core; -import org.graalvm.compiler.core.CompilerThreadFactory.DebugConfigAccess; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugDumpHandler; -import org.graalvm.compiler.debug.GraalDebugConfig; - /** - * A compiler thread is a daemon thread that runs at {@link Thread#MAX_PRIORITY} and executes in the - * context of a thread-local {@linkplain GraalDebugConfig debug configuration}. + * A compiler thread is a daemon thread that runs at {@link Thread#MAX_PRIORITY}. */ public class CompilerThread extends Thread { - private final DebugConfigAccess debugConfigAccess; - - public CompilerThread(Runnable r, String namePrefix, DebugConfigAccess debugConfigAccess) { + public CompilerThread(Runnable r, String namePrefix) { super(r); this.setName(namePrefix + "-" + this.getId()); this.setPriority(Thread.MAX_PRIORITY); this.setDaemon(true); - this.debugConfigAccess = debugConfigAccess; } @Override public void run() { - DebugConfig debugConfig = debugConfigAccess.getDebugConfig(); setContextClassLoader(getClass().getClassLoader()); - try { - super.run(); - } finally { - if (debugConfig != null) { - for (DebugDumpHandler dumpHandler : debugConfig.dumpHandlers()) { - try { - dumpHandler.close(); - } catch (Throwable t) { - } - } - } - } + super.run(); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilerThreadFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilerThreadFactory.java index 4701be8aee3..48dd50d11e1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilerThreadFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilerThreadFactory.java @@ -24,34 +24,19 @@ package org.graalvm.compiler.core; import java.util.concurrent.ThreadFactory; -import org.graalvm.compiler.debug.DebugConfig; - /** * Facility for creating {@linkplain CompilerThread compiler threads}. */ public class CompilerThreadFactory implements ThreadFactory { - /** - * Capability to get a thread-local debug configuration for the current thread. - */ - public interface DebugConfigAccess { - /** - * Get a thread-local debug configuration for the current thread. This will be null if - * debugging is disabled. - */ - DebugConfig getDebugConfig(); - } - protected final String threadNamePrefix; - protected final DebugConfigAccess debugConfigAccess; - public CompilerThreadFactory(String threadNamePrefix, DebugConfigAccess debugConfigAccess) { + public CompilerThreadFactory(String threadNamePrefix) { this.threadNamePrefix = threadNamePrefix; - this.debugConfigAccess = debugConfigAccess; } @Override public Thread newThread(Runnable r) { - return new CompilerThread(r, threadNamePrefix, debugConfigAccess); + return new CompilerThread(r, threadNamePrefix); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java index 26541c81573..597523dae1c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java @@ -22,28 +22,25 @@ */ package org.graalvm.compiler.core; -import static org.graalvm.compiler.core.GraalCompilerOptions.EmitLIRRepeatCount; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; -import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; - import java.util.Collection; import java.util.List; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.util.CompilationAlarm; import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.internal.method.MethodMetricsRootScopeInfo; -import org.graalvm.compiler.lir.BailoutAndRestartBackendException; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.MethodFilter; +import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.lir.LIR; +import org.graalvm.compiler.lir.alloc.OutOfRegistersException; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; import org.graalvm.compiler.lir.framemap.FrameMap; @@ -58,18 +55,16 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.options.OptionValue.OverrideScope; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; -import org.graalvm.compiler.phases.common.instrumentation.ExtractInstrumentationPhase; -import org.graalvm.compiler.phases.schedule.SchedulePhase; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.LowTierContext; import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.code.TargetDescription; @@ -88,12 +83,11 @@ import jdk.vm.ci.meta.VMConstant; */ public class GraalCompiler { - private static final DebugTimer CompilerTimer = Debug.timer("GraalCompiler"); - private static final DebugTimer FrontEnd = Debug.timer("FrontEnd"); - private static final DebugTimer BackEnd = Debug.timer("BackEnd"); - private static final DebugTimer EmitLIR = Debug.timer("EmitLIR"); - private static final DebugTimer EmitCode = Debug.timer("EmitCode"); - private static final LIRGenerationPhase LIR_GENERATION_PHASE = new LIRGenerationPhase(); + private static final TimerKey CompilerTimer = DebugContext.timer("GraalCompiler").doc("Time spent in compilation (excludes code installation)."); + private static final TimerKey FrontEnd = DebugContext.timer("FrontEnd").doc("Time spent processing HIR."); + private static final TimerKey EmitLIR = DebugContext.timer("EmitLIR").doc("Time spent generating LIR from HIR."); + private static final TimerKey EmitCode = DebugContext.timer("EmitCode").doc("Time spent generating machine code from LIR."); + private static final TimerKey BackEnd = DebugContext.timer("BackEnd").doc("Time spent in EmitLIR and EmitCode."); /** * Encapsulates all the inputs to a {@linkplain GraalCompiler#compile(Request) compilation}. @@ -171,123 +165,143 @@ public class GraalCompiler { */ @SuppressWarnings("try") public static T compile(Request r) { - try (Scope s = MethodMetricsRootScopeInfo.createRootScopeIfAbsent(r.installedCodeOwner); - CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod()) { + DebugContext debug = r.graph.getDebug(); + try (CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(r.graph.getOptions())) { assert !r.graph.isFrozen(); - try (Scope s0 = Debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); DebugCloseable a = CompilerTimer.start()) { + try (DebugContext.Scope s0 = debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache()); DebugCloseable a = CompilerTimer.start(debug)) { emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites); emitBackEnd(r.graph, null, r.installedCodeOwner, r.backend, r.compilationResult, r.factory, null, r.lirSuites); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } + checkForRequestedCrash(r.graph); return r.compilationResult; } } + /** + * Checks whether the {@link GraalCompilerOptions#CrashAt} option indicates that the compilation + * of {@code graph} should result in an exception. + * + * @param graph a graph currently being compiled + * @throws RuntimeException if the value of {@link GraalCompilerOptions#CrashAt} matches + * {@code graph.method()} or {@code graph.name} + */ + private static void checkForRequestedCrash(StructuredGraph graph) { + String methodPattern = GraalCompilerOptions.CrashAt.getValue(graph.getOptions()); + if (methodPattern != null) { + String crashLabel = null; + if (graph.name != null && graph.name.contains(methodPattern)) { + crashLabel = graph.name; + } + if (crashLabel == null) { + ResolvedJavaMethod method = graph.method(); + MethodFilter[] filters = MethodFilter.parse(methodPattern); + for (MethodFilter filter : filters) { + if (filter.matches(method)) { + crashLabel = method.format("%H.%n(%p)"); + } + } + } + if (crashLabel != null) { + throw new RuntimeException("Forced crash after compiling " + crashLabel); + } + } + } + /** * Builds the graph, optimizes it. */ @SuppressWarnings("try") public static void emitFrontEnd(Providers providers, TargetProvider target, StructuredGraph graph, PhaseSuite graphBuilderSuite, OptimisticOptimizations optimisticOpts, ProfilingInfo profilingInfo, Suites suites) { - try (Scope s = Debug.scope("FrontEnd"); DebugCloseable a = FrontEnd.start()) { + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope s = debug.scope("FrontEnd"); DebugCloseable a = FrontEnd.start(debug)) { HighTierContext highTierContext = new HighTierContext(providers, graphBuilderSuite, optimisticOpts); if (graph.start().next() == null) { graphBuilderSuite.apply(graph, highTierContext); - new DeadCodeEliminationPhase(Optional).apply(graph); + new DeadCodeEliminationPhase(DeadCodeEliminationPhase.Optionality.Optional).apply(graph); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After parsing"); } else { - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "initial state"); - } - if (UseGraalInstrumentation.getValue()) { - new ExtractInstrumentationPhase().apply(graph, highTierContext); + debug.dump(DebugContext.INFO_LEVEL, graph, "initial state"); } suites.getHighTier().apply(graph, highTierContext); graph.maybeCompress(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After high tier"); MidTierContext midTierContext = new MidTierContext(providers, target, optimisticOpts, profilingInfo); suites.getMidTier().apply(graph, midTierContext); graph.maybeCompress(); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After mid tier"); LowTierContext lowTierContext = new LowTierContext(providers, target); suites.getLowTier().apply(graph, lowTierContext); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After low tier"); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph.getLastSchedule(), "Final HIR schedule"); + debug.dump(DebugContext.BASIC_LEVEL, graph.getLastSchedule(), "Final HIR schedule"); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); + } finally { + graph.checkCancellation(); } } @SuppressWarnings("try") public static void emitBackEnd(StructuredGraph graph, Object stub, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult, CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) { - try (Scope s = Debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start()) { - // Repeatedly run the LIR code generation pass to improve statistical profiling results. - for (int i = 0; i < EmitLIRRepeatCount.getValue(); i++) { - SchedulePhase dummySchedule = new SchedulePhase(); - dummySchedule.apply(graph); - emitLIR(backend, graph, stub, registerConfig, lirSuites); - } - + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope s = debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start(debug)) { LIRGenerationResult lirGen = null; lirGen = emitLIR(backend, graph, stub, registerConfig, lirSuites); - try (Scope s2 = Debug.scope("CodeGen", lirGen, lirGen.getLIR())) { + try (DebugContext.Scope s2 = debug.scope("CodeGen", lirGen, lirGen.getLIR())) { int bytecodeSize = graph.method() == null ? 0 : graph.getBytecodeSize(); compilationResult.setHasUnsafeAccess(graph.hasUnsafeAccess()); emitCode(backend, graph.getAssumptions(), graph.method(), graph.getMethods(), graph.getFields(), bytecodeSize, lirGen, compilationResult, installedCodeOwner, factory); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); + } finally { + graph.checkCancellation(); } } @SuppressWarnings("try") public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) { - OverrideScope overrideScope = null; - LIRSuites lirSuites0 = lirSuites; - while (true) { - try (OverrideScope scope = overrideScope) { - return emitLIR0(backend, graph, stub, registerConfig, lirSuites0); - } catch (BailoutAndRestartBackendException e) { - if (BailoutAndRestartBackendException.Options.LIRUnlockBackendRestart.getValue() && e.shouldRestart()) { - overrideScope = e.getOverrideScope(); - lirSuites0 = e.updateLIRSuites(lirSuites); - if (lirSuites0 != null) { - continue; - } - } - /* - * The BailoutAndRestartBackendException is permanent. If restart fails or is - * disabled we throw the bailout. - */ - throw e; + String registerPressure = GraalOptions.RegisterPressure.getValue(graph.getOptions()); + String[] allocationRestrictedTo = registerPressure == null ? null : registerPressure.split(","); + try { + return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); + } catch (OutOfRegistersException e) { + if (allocationRestrictedTo != null) { + allocationRestrictedTo = null; + return emitLIR0(backend, graph, stub, registerConfig, lirSuites, allocationRestrictedTo); } + /* If the re-execution fails we convert the exception into a "hard" failure */ + throw new GraalError(e); + } finally { + graph.checkCancellation(); } } @SuppressWarnings("try") - private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites) { - try (Scope ds = Debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start()) { + private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, RegisterConfig registerConfig, LIRSuites lirSuites, + String[] allocationRestrictedTo) { + DebugContext debug = graph.getDebug(); + try (DebugContext.Scope ds = debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start(debug)) { + assert !graph.hasValueProxies(); ScheduleResult schedule = graph.getLastSchedule(); Block[] blocks = schedule.getCFG().getBlocks(); Block startBlock = schedule.getCFG().getStartBlock(); assert startBlock != null; assert startBlock.getPredecessorCount() == 0; - LIR lir = null; - AbstractBlockBase[] codeEmittingOrder = null; - AbstractBlockBase[] linearScanOrder = null; - try (Scope s = Debug.scope("ComputeLinearScanOrder", lir)) { - codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock); - linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock); + AbstractBlockBase[] codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock); + AbstractBlockBase[] linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock); + LIR lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder, graph.getOptions(), graph.getDebug()); - lir = new LIR(schedule.getCFG(), linearScanOrder, codeEmittingOrder); - Debug.dump(Debug.INFO_LOG_LEVEL, lir, "After linear scan order"); - } catch (Throwable e) { - throw Debug.handle(e); - } FrameMapBuilder frameMapBuilder = backend.newFrameMapBuilder(registerConfig); LIRGenerationResult lirGenRes = backend.newLIRGenerationResult(graph.compilationId(), lir, frameMapBuilder, graph, stub); LIRGeneratorTool lirGen = backend.newLIRGenerator(lirGenRes); @@ -295,18 +309,20 @@ public class GraalCompiler { // LIR generation LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule); - LIR_GENERATION_PHASE.apply(backend.getTarget(), lirGenRes, context); + new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context); - try (Scope s = Debug.scope("LIRStages", nodeLirGen, lir)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, lir, "After LIR generation"); - LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig)); - Debug.dump(Debug.BASIC_LOG_LEVEL, lir, "Before code generation"); + try (DebugContext.Scope s = debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) { + // Dump LIR along with HIR (the LIR is looked up from context) + debug.dump(DebugContext.BASIC_LEVEL, graph.getLastSchedule(), "After LIR generation"); + LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo)); return result; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); + } finally { + graph.checkCancellation(); } } @@ -323,23 +339,28 @@ public class GraalCompiler { public static LIRGenerationResult emitLowLevel(TargetDescription target, LIRGenerationResult lirGenRes, LIRGeneratorTool lirGen, LIRSuites lirSuites, RegisterAllocationConfig registerAllocationConfig) { + DebugContext debug = lirGenRes.getLIR().getDebug(); PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen); lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, preAllocOptContext); + debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PreAllocationOptimizationStage"); AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig); lirSuites.getAllocationStage().apply(target, lirGenRes, allocContext); + debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After AllocationStage"); PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen); lirSuites.getPostAllocationOptimizationStage().apply(target, lirGenRes, postAllocOptContext); + debug.dump(DebugContext.BASIC_LEVEL, lirGenRes.getLIR(), "After PostAllocationOptimizationStage"); return lirGenRes; } @SuppressWarnings("try") - public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Collection inlinedMethods, Collection accessedFields, + public static void emitCode(Backend backend, Assumptions assumptions, ResolvedJavaMethod rootMethod, Collection inlinedMethods, EconomicSet accessedFields, int bytecodeSize, LIRGenerationResult lirGenRes, CompilationResult compilationResult, ResolvedJavaMethod installedCodeOwner, CompilationResultBuilderFactory factory) { - try (DebugCloseable a = EmitCode.start()) { + DebugContext debug = lirGenRes.getLIR().getDebug(); + try (DebugCloseable a = EmitCode.start(debug)) { FrameMap frameMap = lirGenRes.getFrameMap(); CompilationResultBuilder crb = backend.newCompilationResultBuilder(lirGenRes, frameMap, compilationResult, factory); backend.emitCode(crb, lirGenRes.getLIR(), installedCodeOwner); @@ -352,12 +373,12 @@ public class GraalCompiler { compilationResult.setBytecodeSize(bytecodeSize); } crb.finish(); - if (Debug.isCountEnabled()) { + if (debug.isCountEnabled()) { List ldp = compilationResult.getDataPatches(); JavaKind[] kindValues = JavaKind.values(); - DebugCounter[] dms = new DebugCounter[kindValues.length]; + CounterKey[] dms = new CounterKey[kindValues.length]; for (int i = 0; i < dms.length; i++) { - dms[i] = Debug.counter("DataPatches-%s", kindValues[i]); + dms[i] = DebugContext.counter("DataPatches-%s", kindValues[i]); } for (DataPatch dp : ldp) { @@ -368,17 +389,17 @@ public class GraalCompiler { kind = ((JavaConstant) constant).getJavaKind(); } } - dms[kind.ordinal()].add(1); + dms[kind.ordinal()].add(debug, 1); } - Debug.counter("CompilationResults").increment(); - Debug.counter("CodeBytesEmitted").add(compilationResult.getTargetCodeSize()); - Debug.counter("InfopointsEmitted").add(compilationResult.getInfopoints().size()); - Debug.counter("DataPatches").add(ldp.size()); - Debug.counter("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size()); + DebugContext.counter("CompilationResults").increment(debug); + DebugContext.counter("CodeBytesEmitted").add(debug, compilationResult.getTargetCodeSize()); + DebugContext.counter("InfopointsEmitted").add(debug, compilationResult.getInfopoints().size()); + DebugContext.counter("DataPatches").add(debug, ldp.size()); + DebugContext.counter("ExceptionHandlersEmitted").add(debug, compilationResult.getExceptionHandlers().size()); } - Debug.dump(Debug.BASIC_LOG_LEVEL, compilationResult, "After code generation"); + debug.dump(DebugContext.BASIC_LEVEL, compilationResult, "After code generation"); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java index f8c8a0a30ad..b21a392e8f0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java @@ -22,9 +22,11 @@ */ package org.graalvm.compiler.core; +import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction; +import org.graalvm.compiler.options.EnumOptionKey; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; /** * Options related to {@link GraalCompiler}. @@ -32,22 +34,19 @@ import org.graalvm.compiler.options.OptionValue; public class GraalCompilerOptions { // @formatter:off - @Option(help = "Repeatedly run the LIR code generation pass to improve statistical profiling results.", type = OptionType.Debug) - public static final OptionValue EmitLIRRepeatCount = new OptionValue<>(0); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintFilter = new OptionValue<>(null); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintCompilation = new OptionValue<>(false); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintAfterCompilation = new OptionValue<>(false); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintBailout = new OptionValue<>(false); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue ExitVMOnBailout = new OptionValue<>(false); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue ExitVMOnException = new OptionValue<>(false); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintStackTraceOnException = new OptionValue<>(false); + @Option(help = "Print an informational line to the console for each completed compilation.", type = OptionType.Debug) + public static final OptionKey PrintCompilation = new OptionKey<>(false); + @Option(help = "Pattern (see MethodFilter for format) for method that will trigger an exception when compiled. " + + "This option exists to test handling compilation crashes gracefully.", type = OptionType.Debug) + public static final OptionKey CrashAt = new OptionKey<>(null); + @Option(help = "The action to take when compilation fails with a non-bailout exception.", type = OptionType.User) + public static final EnumOptionKey CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Diagnose, ExceptionAction.HELP); + @Option(help = "The action to take when compilation fails with a bailout exception.", type = OptionType.User) + public static final EnumOptionKey CompilationBailoutAction = new EnumOptionKey<>(ExceptionAction.Silent, ExceptionAction.HELP); + @Option(help = "The maximum number of compilation failures or bailouts to handle with the action specified " + + "by CompilationFailureAction or CompilationBailoutAction before changing to a less verbose action.", type = OptionType.User) + public static final OptionKey MaxCompilationProblemsPerAction = new OptionKey<>(5); + @Option(help = "Alias for CompilationFailureAction=ExitVM.", type = OptionType.User) + public static final OptionKey ExitVMOnException = new OptionKey<>(false); // @formatter:on - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalDebugInitializationParticipant.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalDebugInitializationParticipant.java deleted file mode 100644 index 38cb71febee..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalDebugInitializationParticipant.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.core; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Params; -import org.graalvm.compiler.debug.DebugInitializationParticipant; -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; -import org.graalvm.compiler.serviceprovider.ServiceProvider; - -/** - * A service provider that may modify the initialization of {@link Debug} based on the values - * specified for various {@link GraalDebugConfig} options. - */ -@ServiceProvider(DebugInitializationParticipant.class) -public class GraalDebugInitializationParticipant implements DebugInitializationParticipant { - - @Override - public void apply(Params params) { - if (GraalDebugConfig.areDebugScopePatternsEnabled()) { - params.enable = true; - } - if ("".equals(GraalDebugConfig.Options.Count.getValue())) { - params.enableUnscopedCounters = true; - } - if ("".equals(GraalDebugConfig.Options.MethodMeter.getValue())) { - params.enableUnscopedMethodMetrics = true; - // mm requires full debugging support - params.enable = true; - } - if ("".equals(GraalDebugConfig.Options.Time.getValue())) { - params.enableUnscopedTimers = true; - } - if ("".equals(GraalDebugConfig.Options.TrackMemUse.getValue())) { - params.enableUnscopedMemUseTrackers = true; - } - // unscoped counters/timers/mem use trackers/method metrics should respect method filter - // semantics - if (!params.enable && (params.enableUnscopedMemUseTrackers || params.enableUnscopedMethodMetrics || params.enableUnscopedCounters || params.enableUnscopedTimers) && - GraalDebugConfig.isNotEmpty(GraalDebugConfig.Options.MethodFilter)) { - params.enable = true; - params.enableMethodFilter = true; - } - - if (!params.enableUnscopedMethodMetrics && GraalDebugConfig.Options.MethodMeter.getValue() != null) { - // mm requires full debugging support - params.enable = true; - } - - if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled()) { - if (!params.enable) { - TTY.println("WARNING: MethodMeter is disabled but GlobalMetricsInterceptedByMethodMetrics is enabled. Ignoring MethodMeter and GlobalMetricsInterceptedByMethodMetrics."); - } else { - parseMethodMetricsDebugValueInterception(params); - } - } - if (GraalDebugConfig.isNotEmpty(GraalDebugConfig.Options.MethodMeter) || params.enableUnscopedMethodMetrics) { - if (!MethodMetricsPrinter.methodMetricsDumpingEnabled()) { - TTY.println("WARNING: MethodMeter is enabled but MethodMeter dumping is disabled. Output will not contain MethodMetrics."); - } - } - } - - private static void parseMethodMetricsDebugValueInterception(Params params) { - String interceptionGroup = GraalDebugConfig.Options.GlobalMetricsInterceptedByMethodMetrics.getValue(); - boolean intercepted = false; - if (interceptionGroup.contains("Timers")) { - params.interceptTime = true; - intercepted = true; - } - if (interceptionGroup.contains("Counters")) { - params.interceptCount = true; - intercepted = true; - } - if (interceptionGroup.contains("MemUseTrackers")) { - params.interceptMem = true; - intercepted = true; - } - - if (!intercepted) { - TTY.println("WARNING: Ignoring GlobalMetricsInterceptedByMethodMetrics as the supplied argument does not contain Timers/Counters/MemUseTrackers."); - GraalDebugConfig.Options.GlobalMetricsInterceptedByMethodMetrics.setValue(null); - } - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java index 51aa28e0296..c6d262cd6f1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/LIRGenerationPhase.java @@ -26,9 +26,10 @@ import java.util.List; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.BlockMap; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.lir.phases.LIRPhase; @@ -56,7 +57,8 @@ public class LIRGenerationPhase extends LIRPhase> blockMap) { assert !isProcessed(lirGenRes, b) : "Block already processed " + b; assert verifyPredecessors(lirGenRes, b); nodeLirGen.doBlock(b, graph, blockMap); - if (instructionCounter.isEnabled()) { - instructionCounter.add(lirGenRes.getLIR().getLIRforBlock(b).size()); - } + LIR lir = lirGenRes.getLIR(); + DebugContext debug = lir.getDebug(); + instructionCounter.add(debug, lir.getLIRforBlock(b).size()); } private static boolean verifyPredecessors(LIRGenerationResult lirGenRes, Block block) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java index 4449ecc3e7d..a48abd8cb62 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java @@ -24,13 +24,11 @@ package org.graalvm.compiler.core.gen; import java.util.ArrayDeque; import java.util.Arrays; -import java.util.Map; import java.util.Queue; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.lir.ConstantValue; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.LabelRef; @@ -44,9 +42,12 @@ import org.graalvm.compiler.nodes.virtual.EscapeObjectState; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; import org.graalvm.compiler.virtual.nodes.MaterializedObjectState; import org.graalvm.compiler.virtual.nodes.VirtualObjectState; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.VirtualObject; +import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.JavaValue; @@ -60,16 +61,18 @@ import jdk.vm.ci.meta.Value; public class DebugInfoBuilder { protected final NodeValueMap nodeValueMap; + protected final DebugContext debug; - public DebugInfoBuilder(NodeValueMap nodeValueMap) { + public DebugInfoBuilder(NodeValueMap nodeValueMap, DebugContext debug) { this.nodeValueMap = nodeValueMap; + this.debug = debug; } private static final JavaValue[] NO_JAVA_VALUES = {}; private static final JavaKind[] NO_JAVA_KINDS = {}; - protected final Map virtualObjects = Node.newMap(); - protected final Map objectStates = Node.newIdentityMap(); + protected final EconomicMap virtualObjects = EconomicMap.create(Equivalence.IDENTITY); + protected final EconomicMap objectStates = EconomicMap.create(Equivalence.IDENTITY); protected final Queue pendingVirtualObjects = new ArrayDeque<>(); @@ -118,8 +121,13 @@ public class DebugInfoBuilder { assert currentField != null; int pos = 0; for (int i = 0; i < entryCount; i++) { - if (!currentField.values().get(i).isConstant() || currentField.values().get(i).asJavaConstant().getJavaKind() != JavaKind.Illegal) { - ValueNode value = currentField.values().get(i); + ValueNode value = currentField.values().get(i); + if (value == null) { + JavaKind entryKind = vobjNode.entryKind(i); + values[pos] = JavaConstant.defaultForKind(entryKind.getStackKind()); + slotKinds[pos] = entryKind.getStackKind(); + pos++; + } else if (!value.isConstant() || value.asJavaConstant().getJavaKind() != JavaKind.Illegal) { values[pos] = toJavaValue(value); slotKinds[pos] = toSlotKind(value); pos++; @@ -137,7 +145,11 @@ public class DebugInfoBuilder { vobjValue.setValues(values, slotKinds); } - virtualObjectsArray = virtualObjects.values().toArray(new VirtualObject[virtualObjects.size()]); + virtualObjectsArray = new VirtualObject[virtualObjects.size()]; + int index = 0; + for (VirtualObject value : virtualObjects.getValues()) { + virtualObjectsArray[index++] = value; + } virtualObjects.clear(); } objectStates.clear(); @@ -266,10 +278,10 @@ public class DebugInfoBuilder { return toJavaValue(state.lockAt(i)); } - private static final DebugCounter STATE_VIRTUAL_OBJECTS = Debug.counter("StateVirtualObjects"); - private static final DebugCounter STATE_ILLEGALS = Debug.counter("StateIllegals"); - private static final DebugCounter STATE_VARIABLES = Debug.counter("StateVariables"); - private static final DebugCounter STATE_CONSTANTS = Debug.counter("StateConstants"); + private static final CounterKey STATE_VIRTUAL_OBJECTS = DebugContext.counter("StateVirtualObjects"); + private static final CounterKey STATE_ILLEGALS = DebugContext.counter("StateIllegals"); + private static final CounterKey STATE_VARIABLES = DebugContext.counter("StateVariables"); + private static final CounterKey STATE_CONSTANTS = DebugContext.counter("StateConstants"); private static JavaKind toSlotKind(ValueNode value) { if (value == null) { @@ -298,18 +310,18 @@ public class DebugInfoBuilder { virtualObjects.put(obj, vobject); pendingVirtualObjects.add(obj); } - STATE_VIRTUAL_OBJECTS.increment(); + STATE_VIRTUAL_OBJECTS.increment(debug); return vobject; } } else { // Remove proxies from constants so the constant can be directly embedded. ValueNode unproxied = GraphUtil.unproxify(value); if (unproxied instanceof ConstantNode) { - STATE_CONSTANTS.increment(); + STATE_CONSTANTS.increment(debug); return unproxied.asJavaConstant(); } else if (value != null) { - STATE_VARIABLES.increment(); + STATE_VARIABLES.increment(debug); Value operand = nodeValueMap.operand(value); if (operand instanceof ConstantValue && ((ConstantValue) operand).isJavaConstant()) { return ((ConstantValue) operand).getJavaConstant(); @@ -320,7 +332,7 @@ public class DebugInfoBuilder { } else { // return a dummy value because real value not needed - STATE_ILLEGALS.increment(); + STATE_ILLEGALS.increment(debug); return Value.ILLEGAL; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java index 2c70da10cb2..b5ca686a857 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java @@ -22,18 +22,16 @@ */ package org.graalvm.compiler.core.gen; -import static org.graalvm.compiler.core.common.GraalOptions.MatchExpressions; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; -import static org.graalvm.compiler.lir.LIR.verifyBlock; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isLegal; import static jdk.vm.ci.code.ValueUtil.isRegister; +import static org.graalvm.compiler.core.common.GraalOptions.MatchExpressions; +import static org.graalvm.compiler.debug.DebugOptions.LogVerbose; +import static org.graalvm.compiler.lir.LIR.verifyBlock; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; @@ -41,10 +39,10 @@ import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.common.cfg.BlockMap; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.match.ComplexMatchValue; +import org.graalvm.compiler.core.match.MatchPattern; import org.graalvm.compiler.core.match.MatchRuleRegistry; import org.graalvm.compiler.core.match.MatchStatement; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.graph.GraalGraphError; @@ -99,6 +97,9 @@ import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.spi.NodeValueMap; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.UnmodifiableMapCursor; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.StackSlot; @@ -117,6 +118,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio private final NodeMap nodeOperands; private final DebugInfoBuilder debugInfoBuilder; + private final int traceLIRGeneratorLevel; protected final LIRGenerator gen; @@ -124,16 +126,18 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio private ValueNode lastInstructionPrinted; // Debugging only private final NodeMatchRules nodeMatchRules; - private Map, List> matchRules; + private EconomicMap, List> matchRules; public NodeLIRBuilder(StructuredGraph graph, LIRGeneratorTool gen, NodeMatchRules nodeMatchRules) { this.gen = (LIRGenerator) gen; this.nodeMatchRules = nodeMatchRules; this.nodeOperands = graph.createNodeMap(); this.debugInfoBuilder = createDebugInfoBuilder(graph, this); - if (MatchExpressions.getValue()) { - matchRules = MatchRuleRegistry.lookup(nodeMatchRules.getClass()); + OptionValues options = graph.getOptions(); + if (MatchExpressions.getValue(options)) { + matchRules = MatchRuleRegistry.lookup(nodeMatchRules.getClass(), options, graph.getDebug()); } + traceLIRGeneratorLevel = TTY.isSuppressed() ? 0 : Options.TraceLIRGeneratorLevel.getValue(options); assert nodeMatchRules.lirBuilder == null; nodeMatchRules.lirBuilder = this; @@ -143,9 +147,8 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio return nodeMatchRules; } - @SuppressWarnings({"unused"}) protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) { - return new DebugInfoBuilder(nodeValueMap); + return new DebugInfoBuilder(nodeValueMap, graph.getDebug()); } /** @@ -177,9 +180,10 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio @Override public ValueNode valueForOperand(Value value) { assert nodeOperands != null; - for (Entry entry : nodeOperands.entries()) { - if (entry.getValue().equals(value)) { - return (ValueNode) entry.getKey(); + UnmodifiableMapCursor cursor = nodeOperands.getEntries(); + while (cursor.advance()) { + if (cursor.getValue().equals(value)) { + return (ValueNode) cursor.getKey(); } } return null; @@ -206,7 +210,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio */ public void setMatchResult(Node x, Value operand) { assert operand.equals(ComplexMatchValue.INTERIOR_MATCH) || operand instanceof ComplexMatchValue; - assert operand instanceof ComplexMatchValue || x.getUsageCount() == 1 : "interior matches must be single user"; + assert operand instanceof ComplexMatchValue || MatchPattern.isSingleValueUser(x) : "interior matches must be single user"; assert nodeOperands != null && nodeOperands.get(x) == null : "operand cannot be set twice"; assert !(x instanceof VirtualObjectNode); nodeOperands.set(x, operand); @@ -227,7 +231,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio } public final void append(LIRInstruction op) { - if (Options.PrintIRWithLIR.getValue() && !TTY.isSuppressed()) { + if (Options.PrintIRWithLIR.getValue(nodeOperands.graph().getOptions()) && !TTY.isSuppressed()) { if (currentInstruction != null && lastInstructionPrinted != currentInstruction) { lastInstructionPrinted = currentInstruction; InstructionPrinter ip = new InstructionPrinter(TTY.out()); @@ -238,32 +242,27 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio } protected LIRKind getExactPhiKind(PhiNode phi) { - // TODO (je): maybe turn this into generator-style instead of allocating an ArrayList. - ArrayList values = new ArrayList<>(phi.valueCount()); - for (int i = 0; i < phi.valueCount(); i++) { + LIRKind derivedKind = gen.toRegisterKind(gen.getLIRKind(phi.stamp())); + /* Collect reference information. */ + for (int i = 0; i < phi.valueCount() && !derivedKind.isUnknownReference(); i++) { ValueNode node = phi.valueAt(i); Value value = getOperand(node); + + // get ValueKind for input + final LIRKind valueKind; if (value != null) { - values.add(value.getValueKind(LIRKind.class)); + valueKind = value.getValueKind(LIRKind.class); } else { assert isPhiInputFromBackedge(phi, i) : String.format("Input %s to phi node %s is not yet available although it is not coming from a loop back edge", node, phi); - // non-java constant -> get LIRKind from stamp. LIRKind kind = gen.getLIRKind(node.stamp()); - values.add(gen.toRegisterKind(kind)); + valueKind = gen.toRegisterKind(kind); } + /* Merge the reference information of the derived kind and the input. */ + derivedKind = LIRKind.mergeReferenceInformation(derivedKind, valueKind); } - LIRKind derivedKind = LIRKind.merge(values); - assert verifyPHIKind(derivedKind, gen.getLIRKind(phi.stamp())); return derivedKind; } - private boolean verifyPHIKind(LIRKind derivedKind, LIRKind phiKind) { - PlatformKind derivedPlatformKind = derivedKind.getPlatformKind(); - PlatformKind phiPlatformKind = gen.toRegisterKind(phiKind).getPlatformKind(); - assert derivedPlatformKind.equals(phiPlatformKind) : "kinds don't match: " + derivedPlatformKind + " vs " + phiPlatformKind; - return true; - } - private static boolean isPhiInputFromBackedge(PhiNode phi, int index) { AbstractMergeNode merge = phi.merge(); AbstractEndNode end = merge.phiPredecessorAt(index); @@ -318,6 +317,8 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio @Override @SuppressWarnings("try") public void doBlock(Block block, StructuredGraph graph, BlockMap> blockMap) { + + OptionValues options = graph.getOptions(); try (BlockScope blockScope = gen.getBlockScope(block)) { setSourcePosition(null); @@ -332,7 +333,7 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio AbstractMergeNode merge = (AbstractMergeNode) begin; LabelOp label = (LabelOp) gen.getResult().getLIR().getLIRforBlock(block).get(0); label.setPhiValues(createPhiIn(merge)); - if (Options.PrintIRWithLIR.getValue() && !TTY.isSuppressed()) { + if (Options.PrintIRWithLIR.getValue(options) && !TTY.isSuppressed()) { TTY.println("Created PhiIn: " + label); } @@ -345,11 +346,13 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio // of instructions matchComplexExpressions(nodes); + boolean trace = traceLIRGeneratorLevel >= 3; for (int i = 0; i < nodes.size(); i++) { Node node = nodes.get(i); if (node instanceof ValueNode) { + DebugContext debug = node.getDebug(); ValueNode valueNode = (ValueNode) node; - if (Options.TraceLIRGeneratorLevel.getValue() >= 3) { + if (trace) { TTY.println("LIRGen for " + valueNode); } Value operand = getOperand(valueNode); @@ -365,9 +368,9 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio } } else if (ComplexMatchValue.INTERIOR_MATCH.equals(operand)) { // Doesn't need to be evaluated - Debug.log("interior match for %s", valueNode); + debug.log("interior match for %s", valueNode); } else if (operand instanceof ComplexMatchValue) { - Debug.log("complex match for %s", valueNode); + debug.log("complex match for %s", valueNode); ComplexMatchValue match = (ComplexMatchValue) operand; operand = match.evaluate(this); if (operand != null) { @@ -400,11 +403,12 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio @SuppressWarnings("try") protected void matchComplexExpressions(List nodes) { if (matchRules != null) { - try (Scope s = Debug.scope("MatchComplexExpressions")) { - if (LogVerbose.getValue()) { + DebugContext debug = gen.getResult().getLIR().getDebug(); + try (DebugContext.Scope s = debug.scope("MatchComplexExpressions")) { + if (LogVerbose.getValue(nodeOperands.graph().getOptions())) { int i = 0; for (Node node : nodes) { - Debug.log("%d: (%s) %1S", i++, node.getUsageCount(), node); + debug.log("%d: (%s) %1S", i++, node.getUsageCount(), node); } } @@ -432,19 +436,19 @@ public abstract class NodeLIRBuilder implements NodeLIRBuilderTool, LIRGeneratio protected abstract boolean peephole(ValueNode valueNode); private void doRoot(ValueNode instr) { - if (Options.TraceLIRGeneratorLevel.getValue() >= 2) { + if (traceLIRGeneratorLevel >= 2) { TTY.println("Emitting LIR for instruction " + instr); } currentInstruction = instr; - - Debug.log("Visiting %s", instr); + DebugContext debug = instr.getDebug(); + debug.log("Visiting %s", instr); emitNode(instr); - Debug.log("Operand for %s = %s", instr, getOperand(instr)); + debug.log("Operand for %s = %s", instr, getOperand(instr)); } protected void emitNode(ValueNode node) { - if (Debug.isLogEnabled() && node.stamp().isEmpty()) { - Debug.log("This node has an empty stamp, we are emitting dead code(?): %s", node); + if (node.getDebug().isLogEnabled() && node.stamp().isEmpty()) { + node.getDebug().log("This node has an empty stamp, we are emitting dead code(?): %s", node); } setSourcePosition(node.getNodeSourcePosition()); if (node instanceof LIRLowerable) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java index 280b67041dc..2e281b6cdfe 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeMatchRules.java @@ -56,6 +56,8 @@ import org.graalvm.compiler.nodes.calc.SubNode; import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode; import org.graalvm.compiler.nodes.calc.XorNode; import org.graalvm.compiler.nodes.calc.ZeroExtendNode; +import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; +import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; @@ -87,6 +89,8 @@ import org.graalvm.compiler.nodes.memory.WriteNode; @MatchableNode(nodeClass = OrNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = XorNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = PiNode.class, inputs = {"object"}) +@MatchableNode(nodeClass = LogicCompareAndSwapNode.class, inputs = {"address", "expectedValue", "newValue"}) +@MatchableNode(nodeClass = ValueCompareAndSwapNode.class, inputs = {"address", "expectedValue", "newValue"}) public abstract class NodeMatchRules { NodeLIRBuilder lirBuilder; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java index 9abe43aefff..9e9161b9501 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java @@ -22,21 +22,21 @@ */ package org.graalvm.compiler.core.match; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; +import static org.graalvm.compiler.debug.DebugOptions.LogVerbose; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.core.match.MatchPattern.Result; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; /** * Container for state captured during a match. @@ -49,7 +49,7 @@ public class MatchContext { private final MatchStatement rule; - private Map namedNodes; + private EconomicMap namedNodes; private ArrayList consumed; @@ -85,7 +85,7 @@ public class MatchContext { public Result captureNamedValue(String name, Class type, Node value) { if (namedNodes == null) { - namedNodes = new HashMap<>(2); + namedNodes = EconomicMap.create(Equivalence.DEFAULT); } NamedNode current = namedNodes.get(name); if (current == null) { @@ -109,11 +109,12 @@ public class MatchContext { // don't interfere with this match. continue; } else if ((consumed == null || !consumed.contains(node)) && node != root) { - if (LogVerbose.getValue()) { - Debug.log("unexpected node %s", node); + if (LogVerbose.getValue(root.getOptions())) { + DebugContext debug = root.getDebug(); + debug.log("unexpected node %s", node); for (int j = startIndex; j <= endIndex; j++) { Node theNode = nodes.get(j); - Debug.log("%s(%s) %1s", (consumed != null && consumed.contains(theNode) || theNode == root) ? "*" : " ", theNode.getUsageCount(), theNode); + debug.log("%s(%s) %1s", (consumed != null && consumed.contains(theNode) || theNode == root) ? "*" : " ", theNode.getUsageCount(), theNode); } } return Result.notSafe(node, rule.getPattern()); @@ -130,9 +131,10 @@ public class MatchContext { */ public void setResult(ComplexMatchResult result) { ComplexMatchValue value = new ComplexMatchValue(result); - if (Debug.isLogEnabled()) { - Debug.log("matched %s %s", rule.getName(), rule.getPattern()); - Debug.log("with nodes %s", rule.formatMatch(root)); + DebugContext debug = root.getDebug(); + if (debug.isLogEnabled()) { + debug.log("matched %s %s", rule.getName(), rule.getPattern()); + debug.log("with nodes %s", rule.formatMatch(root)); } if (consumed != null) { for (Node node : consumed) { @@ -151,7 +153,7 @@ public class MatchContext { * @return Result.OK if the node can be safely consumed. */ public Result consume(Node node) { - assert node.getUsageCount() <= 1 : "should have already been checked"; + assert MatchPattern.isSingleValueUser(node) : "should have already been checked"; // Check NOT_IN_BLOCK first since that usually implies ALREADY_USED int index = nodes.indexOf(node); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java index 171c2dbfc34..e76e4400a62 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchPattern.java @@ -22,10 +22,11 @@ */ package org.graalvm.compiler.core.match; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.Position; +import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.Verbosity; /** @@ -61,12 +62,12 @@ public class MatchPattern { this.matcher = matcher; } - private static final DebugCounter MatchResult_WRONG_CLASS = Debug.counter("MatchResult_WRONG_CLASS"); - private static final DebugCounter MatchResult_NAMED_VALUE_MISMATCH = Debug.counter("MatchResult_NAMED_VALUE_MISMATCH"); - private static final DebugCounter MatchResult_TOO_MANY_USERS = Debug.counter("MatchResult_TOO_MANY_USERS"); - private static final DebugCounter MatchResult_NOT_IN_BLOCK = Debug.counter("MatchResult_NOT_IN_BLOCK"); - private static final DebugCounter MatchResult_NOT_SAFE = Debug.counter("MatchResult_NOT_SAFE"); - private static final DebugCounter MatchResult_ALREADY_USED = Debug.counter("MatchResult_ALREADY_USED"); + private static final CounterKey MatchResult_WRONG_CLASS = DebugContext.counter("MatchResult_WRONG_CLASS"); + private static final CounterKey MatchResult_NAMED_VALUE_MISMATCH = DebugContext.counter("MatchResult_NAMED_VALUE_MISMATCH"); + private static final CounterKey MatchResult_TOO_MANY_USERS = DebugContext.counter("MatchResult_TOO_MANY_USERS"); + private static final CounterKey MatchResult_NOT_IN_BLOCK = DebugContext.counter("MatchResult_NOT_IN_BLOCK"); + private static final CounterKey MatchResult_NOT_SAFE = DebugContext.counter("MatchResult_NOT_SAFE"); + private static final CounterKey MatchResult_ALREADY_USED = DebugContext.counter("MatchResult_ALREADY_USED"); static final Result OK = new Result(MatchResultCode.OK, null, null); private static final Result CACHED_WRONG_CLASS = new Result(MatchResultCode.WRONG_CLASS, null, null); @@ -77,33 +78,33 @@ public class MatchPattern { private static final Result CACHED_ALREADY_USED = new Result(MatchResultCode.ALREADY_USED, null, null); static Result wrongClass(Node node, MatchPattern matcher) { - MatchResult_WRONG_CLASS.increment(); - return Debug.isLogEnabled() ? new Result(MatchResultCode.WRONG_CLASS, node, matcher) : CACHED_WRONG_CLASS; + MatchResult_WRONG_CLASS.increment(node.getDebug()); + return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.WRONG_CLASS, node, matcher) : CACHED_WRONG_CLASS; } static Result namedValueMismatch(Node node, MatchPattern matcher) { - MatchResult_NAMED_VALUE_MISMATCH.increment(); - return Debug.isLogEnabled() ? new Result(MatchResultCode.NAMED_VALUE_MISMATCH, node, matcher) : CACHED_NAMED_VALUE_MISMATCH; + MatchResult_NAMED_VALUE_MISMATCH.increment(node.getDebug()); + return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.NAMED_VALUE_MISMATCH, node, matcher) : CACHED_NAMED_VALUE_MISMATCH; } static Result tooManyUsers(Node node, MatchPattern matcher) { - MatchResult_TOO_MANY_USERS.increment(); - return Debug.isLogEnabled() ? new Result(MatchResultCode.TOO_MANY_USERS, node, matcher) : CACHED_TOO_MANY_USERS; + MatchResult_TOO_MANY_USERS.increment(node.getDebug()); + return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.TOO_MANY_USERS, node, matcher) : CACHED_TOO_MANY_USERS; } static Result notInBlock(Node node, MatchPattern matcher) { - MatchResult_NOT_IN_BLOCK.increment(); - return Debug.isLogEnabled() ? new Result(MatchResultCode.NOT_IN_BLOCK, node, matcher) : CACHED_NOT_IN_BLOCK; + MatchResult_NOT_IN_BLOCK.increment(node.getDebug()); + return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.NOT_IN_BLOCK, node, matcher) : CACHED_NOT_IN_BLOCK; } static Result notSafe(Node node, MatchPattern matcher) { - MatchResult_NOT_SAFE.increment(); - return Debug.isLogEnabled() ? new Result(MatchResultCode.NOT_SAFE, node, matcher) : CACHED_NOT_SAFE; + MatchResult_NOT_SAFE.increment(node.getDebug()); + return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.NOT_SAFE, node, matcher) : CACHED_NOT_SAFE; } static Result alreadyUsed(Node node, MatchPattern matcher) { - MatchResult_ALREADY_USED.increment(); - return Debug.isLogEnabled() ? new Result(MatchResultCode.ALREADY_USED, node, matcher) : CACHED_ALREADY_USED; + MatchResult_ALREADY_USED.increment(node.getDebug()); + return node.getDebug().isLogEnabled() ? new Result(MatchResultCode.ALREADY_USED, node, matcher) : CACHED_ALREADY_USED; } @Override @@ -252,7 +253,7 @@ public class MatchPattern { } if (singleUser && !atRoot) { - if (node.getUsageCount() > 1) { + if (!isSingleValueUser(node)) { return Result.tooManyUsers(node, statement.getPattern()); } } @@ -267,6 +268,31 @@ public class MatchPattern { return result; } + public static boolean isSingleValueUser(Node node) { + int valueUsage = node.getUsageCount(); + if (valueUsage == 1) { + return true; + } + if (node.isAllowedUsageType(InputType.Guard)) { + // See if the other usages are non-Value usages. + valueUsage = 0; + for (Node usage : node.usages()) { + for (Position input : usage.inputPositions()) { + if (input.getInputType() == InputType.Value && input.get(usage) == node) { + valueUsage++; + if (valueUsage > 1) { + // Too many value users + return false; + } + } + } + } + assert valueUsage == 1; + return true; + } + return false; + } + /** * For a node starting at root, produce a String showing the inputs that matched against this * rule. It's assumed that a match has already succeeded against this rule, otherwise the diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java index bab5c593b20..b352ddc61f5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java @@ -22,23 +22,23 @@ */ package org.graalvm.compiler.core.match; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; +import static org.graalvm.compiler.debug.DebugOptions.LogVerbose; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; import org.graalvm.compiler.core.gen.NodeMatchRules; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Edges; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.Position; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.serviceprovider.GraalServices; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; +import org.graalvm.util.MapCursor; public class MatchRuleRegistry { @@ -67,31 +67,33 @@ public class MatchRuleRegistry { return result; } - private static final HashMap, Map, List>> registry = new HashMap<>(); + private static final EconomicMap, EconomicMap, List>> registry = EconomicMap.create(Equivalence.IDENTITY); /** * Collect all the {@link MatchStatement}s defined by the superclass chain of theClass. * * @param theClass + * @param options * @return the set of {@link MatchStatement}s applicable to theClass. */ @SuppressWarnings("try") - public static synchronized Map, List> lookup(Class theClass) { - Map, List> result = registry.get(theClass); + public static synchronized EconomicMap, List> lookup(Class theClass, OptionValues options, DebugContext debug) { + EconomicMap, List> result = registry.get(theClass); if (result == null) { - Map, List> rules = createRules(theClass); + EconomicMap, List> rules = createRules(theClass); registry.put(theClass, rules); assert registry.get(theClass) == rules; result = rules; - if (LogVerbose.getValue()) { - try (Scope s = Debug.scope("MatchComplexExpressions")) { - Debug.log("Match rules for %s", theClass.getSimpleName()); - for (Entry, List> entry : result.entrySet()) { - Debug.log(" For node class: %s", entry.getKey()); - for (MatchStatement statement : entry.getValue()) { - Debug.log(" %s", statement.getPattern()); + if (LogVerbose.getValue(options)) { + try (DebugContext.Scope s = debug.scope("MatchComplexExpressions")) { + debug.log("Match rules for %s", theClass.getSimpleName()); + MapCursor, List> cursor = result.getEntries(); + while (cursor.advance()) { + debug.log(" For node class: %s", cursor.getKey()); + for (MatchStatement statement : cursor.getValue()) { + debug.log(" %s", statement.getPattern()); } } } @@ -108,8 +110,9 @@ public class MatchRuleRegistry { * This is a separate, public method so that external clients can create rules with a custom * lookup and without the default caching behavior. */ - public static Map, List> createRules(Class theClass) { - HashMap, MatchStatementSet> matchSets = new HashMap<>(); + @SuppressWarnings("unchecked") + public static EconomicMap, List> createRules(Class theClass) { + EconomicMap, MatchStatementSet> matchSets = EconomicMap.create(Equivalence.IDENTITY); Iterable sl = GraalServices.load(MatchStatementSet.class); for (MatchStatementSet rules : sl) { matchSets.put(rules.forClass(), rules); @@ -117,8 +120,8 @@ public class MatchRuleRegistry { // Walk the class hierarchy collecting lists and merge them together. The subclass // rules are first which gives them preference over earlier rules. - Map, List> rules = new HashMap<>(); - Class currentClass = theClass; + EconomicMap, List> rules = EconomicMap.create(Equivalence.IDENTITY); + Class currentClass = theClass; do { MatchStatementSet matchSet = matchSets.get(currentClass); if (matchSet != null) { @@ -133,7 +136,7 @@ public class MatchRuleRegistry { current.add(statement); } } - currentClass = currentClass.getSuperclass(); + currentClass = (Class) currentClass.getSuperclass(); } while (currentClass != NodeMatchRules.class); return rules; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java index 7d4fbb0ae8c..4514aaa9952 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchStatement.java @@ -22,28 +22,28 @@ */ package org.graalvm.compiler.core.match; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.LogVerbose; +import static org.graalvm.compiler.debug.DebugOptions.LogVerbose; import java.util.List; -import jdk.vm.ci.meta.Value; - import org.graalvm.compiler.core.gen.NodeLIRBuilder; import org.graalvm.compiler.core.match.MatchPattern.MatchResultCode; import org.graalvm.compiler.core.match.MatchPattern.Result; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.GraalGraphError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodeinfo.Verbosity; +import jdk.vm.ci.meta.Value; + /** * A named {@link MatchPattern} along with a {@link MatchGenerator} that can be evaluated to replace * one or more {@link Node}s with a single {@link Value}. */ public class MatchStatement { - private static final DebugCounter MatchStatementSuccess = Debug.counter("MatchStatementSuccess"); + private static final CounterKey MatchStatementSuccess = DebugContext.counter("MatchStatementSuccess"); /** * A printable name for this statement. Usually it's just the name of the method doing the @@ -83,6 +83,7 @@ public class MatchStatement { * evaluated by the NodeLIRBuilder. */ public boolean generate(NodeLIRBuilder builder, int index, Node node, List nodes) { + DebugContext debug = node.getDebug(); assert index == nodes.indexOf(node); // Check that the basic shape matches Result result = pattern.matchShape(node, this); @@ -97,19 +98,19 @@ public class MatchStatement { ComplexMatchResult value = generatorMethod.match(builder.getNodeMatchRules(), buildArgList(context)); if (value != null) { context.setResult(value); - MatchStatementSuccess.increment(); - Debug.counter("MatchStatement[%s]", getName()).increment(); + MatchStatementSuccess.increment(debug); + DebugContext.counter("MatchStatement[%s]", getName()).increment(debug); return true; } // The pattern matched but some other code generation constraint disallowed code // generation for the pattern. - if (LogVerbose.getValue()) { - Debug.log("while matching %s|%s %s %s returned null", context.getRoot().toString(Verbosity.Id), context.getRoot().getClass().getSimpleName(), getName(), generatorMethod.getName()); - Debug.log("with nodes %s", formatMatch(node)); + if (LogVerbose.getValue(node.getOptions())) { + debug.log("while matching %s|%s %s %s returned null", context.getRoot().toString(Verbosity.Id), context.getRoot().getClass().getSimpleName(), getName(), generatorMethod.getName()); + debug.log("with nodes %s", formatMatch(node)); } } else { - if (LogVerbose.getValue() && result.code != MatchResultCode.WRONG_CLASS) { - Debug.log("while matching %s|%s %s %s", context.getRoot().toString(Verbosity.Id), context.getRoot().getClass().getSimpleName(), getName(), result); + if (LogVerbose.getValue(node.getOptions()) && result.code != MatchResultCode.WRONG_CLASS) { + debug.log("while matching %s|%s %s %s", context.getRoot().toString(Verbosity.Id), context.getRoot().getClass().getSimpleName(), getName(), result); } } return false; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java index c2ff09dff27..d714edea6a4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAlloc import org.graalvm.compiler.lir.phases.PostAllocationOptimizationStage; import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; import org.graalvm.compiler.lir.phases.PreAllocationOptimizationStage; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -38,33 +39,32 @@ import org.graalvm.compiler.phases.tiers.MidTierContext; public class CoreCompilerConfiguration implements CompilerConfiguration { @Override - public PhaseSuite createHighTier() { - return new HighTier(); + public PhaseSuite createHighTier(OptionValues options) { + return new HighTier(options); } @Override - public PhaseSuite createMidTier() { - return new MidTier(); + public PhaseSuite createMidTier(OptionValues options) { + return new MidTier(options); } @Override - public PhaseSuite createLowTier() { - return new LowTier(); + public PhaseSuite createLowTier(OptionValues options) { + return new LowTier(options); } @Override - public LIRPhaseSuite createPreAllocationOptimizationStage() { - return new PreAllocationOptimizationStage(); + public LIRPhaseSuite createPreAllocationOptimizationStage(OptionValues options) { + return new PreAllocationOptimizationStage(options); } @Override - public LIRPhaseSuite createAllocationStage() { - return new AllocationStage(); + public LIRPhaseSuite createAllocationStage(OptionValues options) { + return new AllocationStage(options); } @Override - public LIRPhaseSuite createPostAllocationOptimizationStage() { - return new PostAllocationOptimizationStage(); + public LIRPhaseSuite createPostAllocationOptimizationStage(OptionValues options) { + return new PostAllocationOptimizationStage(options); } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java index 307a59b3049..12fc5f99dae 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.lir.phases.EconomyPreAllocationOptimizationStage; import org.graalvm.compiler.lir.phases.LIRPhaseSuite; import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext; import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -38,32 +39,32 @@ import org.graalvm.compiler.phases.tiers.MidTierContext; public class EconomyCompilerConfiguration implements CompilerConfiguration { @Override - public PhaseSuite createHighTier() { - return new EconomyHighTier(); + public PhaseSuite createHighTier(OptionValues options) { + return new EconomyHighTier(options); } @Override - public PhaseSuite createMidTier() { - return new EconomyMidTier(); + public PhaseSuite createMidTier(OptionValues options) { + return new EconomyMidTier(options); } @Override - public PhaseSuite createLowTier() { - return new EconomyLowTier(); + public PhaseSuite createLowTier(OptionValues options) { + return new EconomyLowTier(options); } @Override - public LIRPhaseSuite createPreAllocationOptimizationStage() { + public LIRPhaseSuite createPreAllocationOptimizationStage(OptionValues options) { return new EconomyPreAllocationOptimizationStage(); } @Override - public LIRPhaseSuite createAllocationStage() { - return new EconomyAllocationStage(); + public LIRPhaseSuite createAllocationStage(OptionValues options) { + return new EconomyAllocationStage(options); } @Override - public LIRPhaseSuite createPostAllocationOptimizationStage() { + public LIRPhaseSuite createPostAllocationOptimizationStage(OptionValues options) { return new EconomyPostAllocationOptimizationStage(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java index 76efa541752..fb4b35c5bef 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyHighTier.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.core.phases; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; @@ -32,9 +33,9 @@ import org.graalvm.compiler.phases.tiers.HighTierContext; public class EconomyHighTier extends PhaseSuite { - public EconomyHighTier() { + public EconomyHighTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java index db1b0f11018..3950f8ead8a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyLowTier.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.core.phases; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.ExpandLogicPhase; @@ -34,9 +35,9 @@ import org.graalvm.compiler.phases.tiers.LowTierContext; public class EconomyLowTier extends PhaseSuite { - public EconomyLowTier() { + public EconomyLowTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java index c6350bc2ffd..504bed773bc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyMidTier.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.core.phases; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase; @@ -36,9 +37,9 @@ import org.graalvm.compiler.phases.tiers.MidTierContext; public class EconomyMidTier extends PhaseSuite { - public EconomyMidTier() { + public EconomyMidTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } appendPhase(new RemoveValueProxyPhase()); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java index bb7236d6ced..b8af0a4b031 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java @@ -22,11 +22,7 @@ */ package org.graalvm.compiler.core.phases; -import java.util.Set; -import java.util.stream.Collectors; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Graph.NodeEvent; import org.graalvm.compiler.graph.Graph.NodeEventScope; import org.graalvm.compiler.graph.Node; @@ -36,6 +32,8 @@ import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.util.HashSetNodeEventListener; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.util.EconomicSet; +import org.graalvm.util.Equivalence; /** * A utility phase for detecting when a phase would change the graph and reporting extra information @@ -69,32 +67,38 @@ public class GraphChangeMonitoringPhase extends PhaseSui * having their inputs change are the main interesting differences. */ HashSetNodeEventListener listener = new HashSetNodeEventListener().exclude(NodeEvent.NODE_ADDED); - StructuredGraph graphCopy = (StructuredGraph) graph.copy(); + StructuredGraph graphCopy = (StructuredGraph) graph.copy(graph.getDebug()); + DebugContext debug = graph.getDebug(); try (NodeEventScope s = graphCopy.trackNodeEvents(listener)) { - try (Scope s2 = Debug.sandbox("WithoutMonitoring", null)) { + try (DebugContext.Scope s2 = debug.sandbox("WithoutMonitoring", null)) { super.run(graphCopy, context); } catch (Throwable t) { - Debug.handle(t); + debug.handle(t); } } - /* - * Ignore LogicConstantNode since those are sometimes created and deleted as part of running - * a phase. - */ - if (listener.getNodes().stream().filter(e -> !(e instanceof LogicConstantNode)).findFirst().isPresent()) { + + EconomicSet filteredNodes = EconomicSet.create(Equivalence.IDENTITY); + for (Node n : listener.getNodes()) { + if (n instanceof LogicConstantNode) { + // Ignore LogicConstantNode since those are sometimes created and deleted as part of + // running a phase. + } else { + filteredNodes.add(n); + } + } + if (!filteredNodes.isEmpty()) { /* rerun it on the real graph in a new Debug scope so Dump and Log can find it. */ listener = new HashSetNodeEventListener(); try (NodeEventScope s = graph.trackNodeEvents(listener)) { - try (Scope s2 = Debug.scope("WithGraphChangeMonitoring")) { - if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "*** Before phase %s", getName()); + try (DebugContext.Scope s2 = debug.scope("WithGraphChangeMonitoring")) { + if (debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) { + debug.dump(DebugContext.DETAILED_LEVEL, graph, "*** Before phase %s", getName()); } super.run(graph, context); - Set collect = listener.getNodes().stream().filter(e -> !e.isAlive()).filter(e -> !(e instanceof LogicConstantNode)).collect(Collectors.toSet()); - if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) { - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "*** After phase %s %s", getName(), collect); + if (debug.isDumpEnabled(DebugContext.DETAILED_LEVEL)) { + debug.dump(DebugContext.DETAILED_LEVEL, graph, "*** After phase %s %s", getName(), filteredNodes); } - Debug.log("*** %s %s %s\n", message, graph, collect); + debug.log("*** %s %s %s\n", message, graph, filteredNodes); } } } else { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java index 675c1dd9d30..358d6cb0b4f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/HighTier.java @@ -29,8 +29,8 @@ import static org.graalvm.compiler.core.common.GraalOptions.LoopPeeling; import static org.graalvm.compiler.core.common.GraalOptions.LoopUnswitch; import static org.graalvm.compiler.core.common.GraalOptions.OptConvertDeoptsToGuards; import static org.graalvm.compiler.core.common.GraalOptions.OptLoopTransform; +import static org.graalvm.compiler.core.common.GraalOptions.OptReadElimination; import static org.graalvm.compiler.core.common.GraalOptions.PartialEscapeAnalysis; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional; import org.graalvm.compiler.loop.DefaultLoopPolicies; @@ -40,8 +40,9 @@ import org.graalvm.compiler.loop.phases.LoopPeelingPhase; import org.graalvm.compiler.loop.phases.LoopUnswitchingPhase; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.ConvertDeoptimizeToGuardPhase; @@ -51,8 +52,8 @@ import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; -import org.graalvm.compiler.phases.common.instrumentation.HighTierReconcileInstrumentationPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; public class HighTier extends PhaseSuite { @@ -61,57 +62,58 @@ public class HighTier extends PhaseSuite { // @formatter:off @Option(help = "Enable inlining", type = OptionType.Expert) - public static final OptionValue Inline = new OptionValue<>(true); + public static final OptionKey Inline = new OptionKey<>(true); // @formatter:on } - public HighTier() { + public HighTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } appendPhase(canonicalizer); - if (Options.Inline.getValue()) { + if (Options.Inline.getValue(options)) { appendPhase(new InliningPhase(canonicalizer)); appendPhase(new DeadCodeEliminationPhase(Optional)); - - if (ConditionalElimination.getValue()) { - appendPhase(canonicalizer); - appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, false)); - } } - if (OptConvertDeoptsToGuards.getValue()) { + if (OptConvertDeoptsToGuards.getValue(options)) { appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new ConvertDeoptimizeToGuardPhase())); } + if (ConditionalElimination.getValue(options)) { + appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, false)); + } + LoopPolicies loopPolicies = createLoopPolicies(); - if (FullUnroll.getValue()) { + if (FullUnroll.getValue(options)) { appendPhase(new LoopFullUnrollPhase(canonicalizer, loopPolicies)); } - if (OptLoopTransform.getValue()) { - if (LoopPeeling.getValue()) { + if (OptLoopTransform.getValue(options)) { + if (LoopPeeling.getValue(options)) { appendPhase(new LoopPeelingPhase(loopPolicies)); } - if (LoopUnswitch.getValue()) { + if (LoopUnswitch.getValue(options)) { appendPhase(new LoopUnswitchingPhase(loopPolicies)); } } appendPhase(canonicalizer); - if (PartialEscapeAnalysis.getValue()) { - appendPhase(new PartialEscapePhase(true, canonicalizer)); + if (PartialEscapeAnalysis.getValue(options)) { + appendPhase(new PartialEscapePhase(true, canonicalizer, options)); } + + if (OptReadElimination.getValue(options)) { + appendPhase(new EarlyReadEliminationPhase(canonicalizer)); + } + appendPhase(new RemoveValueProxyPhase()); appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER)); - if (UseGraalInstrumentation.getValue()) { - appendPhase(new HighTierReconcileInstrumentationPhase()); - } } public LoopPolicies createLoopPolicies() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java index 57c72bc63be..8ba0d99d1fd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/LowTier.java @@ -22,26 +22,26 @@ */ package org.graalvm.compiler.core.phases; -import static org.graalvm.compiler.core.common.GraalOptions.ConditionalElimination; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; import org.graalvm.compiler.phases.common.ExpandLogicPhase; -import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; +import org.graalvm.compiler.phases.common.FixReadsPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.ProfileCompiledMethodsPhase; -import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; +import org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase; import org.graalvm.compiler.phases.common.UseTrappingNullChecksPhase; -import org.graalvm.compiler.phases.common.instrumentation.InlineInstrumentationPhase; import org.graalvm.compiler.phases.schedule.SchedulePhase; +import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; import org.graalvm.compiler.phases.tiers.LowTierContext; public class LowTier extends PhaseSuite { @@ -50,41 +50,38 @@ public class LowTier extends PhaseSuite { // @formatter:off @Option(help = "", type = OptionType.Debug) - public static final OptionValue ProfileCompiledMethods = new OptionValue<>(false); + public static final OptionKey ProfileCompiledMethods = new OptionKey<>(false); // @formatter:on } - public LowTier() { + public LowTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + CanonicalizerPhase canonicalizerWithoutGVN = new CanonicalizerPhase(); + canonicalizerWithoutGVN.disableGVN(); + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); + canonicalizerWithoutGVN.disableReadCanonicalization(); } - if (Options.ProfileCompiledMethods.getValue()) { + if (Options.ProfileCompiledMethods.getValue(options)) { appendPhase(new ProfileCompiledMethodsPhase()); } appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER)); - if (UseGraalInstrumentation.getValue()) { - appendPhase(new InlineInstrumentationPhase()); - } - - appendPhase(new RemoveValueProxyPhase()); appendPhase(new ExpandLogicPhase()); - /* Cleanup IsNull checks resulting from MID_TIER/LOW_TIER lowering and ExpandLogic phase. */ - if (ConditionalElimination.getValue()) { - appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, false)); - /* Canonicalizer may create some new ShortCircuitOrNodes so clean them up. */ - appendPhase(new ExpandLogicPhase()); - } + appendPhase(new FixReadsPhase(true, new SchedulePhase(GraalOptions.StressTestEarlyReads.getValue(options) ? SchedulingStrategy.EARLIEST : SchedulingStrategy.LATEST_OUT_OF_LOOPS))); + + appendPhase(canonicalizerWithoutGVN); appendPhase(new UseTrappingNullChecksPhase()); appendPhase(new DeadCodeEliminationPhase(Required)); + appendPhase(new PropagateDeoptimizeProbabilityPhase()); + appendPhase(new SchedulePhase(SchedulePhase.SchedulingStrategy.FINAL_SCHEDULE)); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java index dc79e143ae1..32036a60759 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/MidTier.java @@ -25,17 +25,19 @@ package org.graalvm.compiler.core.phases; import static org.graalvm.compiler.core.common.GraalOptions.ConditionalElimination; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.core.common.GraalOptions.OptDeoptimizationGrouping; -import static org.graalvm.compiler.core.common.GraalOptions.OptEliminatePartiallyRedundantGuards; import static org.graalvm.compiler.core.common.GraalOptions.OptFloatingReads; -import static org.graalvm.compiler.core.common.GraalOptions.OptPushThroughPi; -import static org.graalvm.compiler.core.common.GraalOptions.OptReadElimination; +import static org.graalvm.compiler.core.common.GraalOptions.OptLoopTransform; +import static org.graalvm.compiler.core.common.GraalOptions.PartialUnroll; import static org.graalvm.compiler.core.common.GraalOptions.ReassociateInvariants; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; import static org.graalvm.compiler.core.common.GraalOptions.VerifyHeapAtReturn; +import org.graalvm.compiler.loop.DefaultLoopPolicies; +import org.graalvm.compiler.loop.LoopPolicies; +import org.graalvm.compiler.loop.phases.LoopPartialUnrollPhase; import org.graalvm.compiler.loop.phases.LoopSafepointEliminationPhase; import org.graalvm.compiler.loop.phases.ReassociateInvariantPhase; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.DeoptimizationGroupingPhase; @@ -47,82 +49,59 @@ import org.graalvm.compiler.phases.common.IterativeConditionalEliminationPhase; import org.graalvm.compiler.phases.common.LockEliminationPhase; import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase; import org.graalvm.compiler.phases.common.LoweringPhase; -import org.graalvm.compiler.phases.common.OptimizeGuardAnchorsPhase; -import org.graalvm.compiler.phases.common.PushThroughPiPhase; -import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; -import org.graalvm.compiler.phases.common.ValueAnchorCleanupPhase; import org.graalvm.compiler.phases.common.VerifyHeapAtReturnPhase; -import org.graalvm.compiler.phases.common.instrumentation.MidTierReconcileInstrumentationPhase; import org.graalvm.compiler.phases.tiers.MidTierContext; -import org.graalvm.compiler.virtual.phases.ea.EarlyReadEliminationPhase; public class MidTier extends PhaseSuite { - public MidTier() { + public MidTier(OptionValues options) { CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { canonicalizer.disableReadCanonicalization(); } - if (OptPushThroughPi.getValue()) { - appendPhase(new PushThroughPiPhase()); - } - - appendPhase(canonicalizer); - - appendPhase(new ValueAnchorCleanupPhase()); appendPhase(new LockEliminationPhase()); - if (OptReadElimination.getValue()) { - appendPhase(new EarlyReadEliminationPhase(canonicalizer)); - } - - if (OptFloatingReads.getValue()) { + if (OptFloatingReads.getValue(options)) { appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new FloatingReadPhase())); } - appendPhase(new RemoveValueProxyPhase()); - appendPhase(canonicalizer); - - if (OptEliminatePartiallyRedundantGuards.getValue()) { - appendPhase(new OptimizeGuardAnchorsPhase()); - } - - if (ConditionalElimination.getValue()) { + if (ConditionalElimination.getValue(options)) { appendPhase(new IterativeConditionalEliminationPhase(canonicalizer, true)); } - if (OptEliminatePartiallyRedundantGuards.getValue()) { - appendPhase(new OptimizeGuardAnchorsPhase()); - } - - appendPhase(canonicalizer); - - appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new LoopSafepointEliminationPhase())); + appendPhase(new LoopSafepointEliminationPhase()); appendPhase(new LoopSafepointInsertionPhase()); - appendPhase(new IncrementalCanonicalizerPhase<>(canonicalizer, new GuardLoweringPhase())); + appendPhase(new GuardLoweringPhase()); - if (VerifyHeapAtReturn.getValue()) { + if (VerifyHeapAtReturn.getValue(options)) { appendPhase(new VerifyHeapAtReturnPhase()); } appendPhase(new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER)); - if (UseGraalInstrumentation.getValue()) { - appendPhase(new MidTierReconcileInstrumentationPhase()); - } appendPhase(new FrameStateAssignmentPhase()); - if (ReassociateInvariants.getValue()) { + LoopPolicies loopPolicies = createLoopPolicies(); + if (OptLoopTransform.getValue(options)) { + if (PartialUnroll.getValue(options)) { + appendPhase(new LoopPartialUnrollPhase(loopPolicies, canonicalizer)); + } + } + if (ReassociateInvariants.getValue(options)) { appendPhase(new ReassociateInvariantPhase()); } - if (OptDeoptimizationGrouping.getValue()) { + if (OptDeoptimizationGrouping.getValue(options)) { appendPhase(new DeoptimizationGroupingPhase()); } appendPhase(canonicalizer); } + + public LoopPolicies createLoopPolicies() { + return new DefaultLoopPolicies(); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java index 53214afb9d3..c5d39002411 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.core.target; -import java.util.Set; +import java.util.ArrayList; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.code.CompilationResult; @@ -31,8 +31,7 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; @@ -45,6 +44,7 @@ import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.phases.tiers.SuitesProvider; import org.graalvm.compiler.phases.tiers.TargetProvider; import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.CodeCacheProvider; @@ -67,12 +67,18 @@ import jdk.vm.ci.meta.SpeculationLog; public abstract class Backend implements TargetProvider, ValueKindFactory { private final Providers providers; + private final ArrayList codeInstallationTaskFactories; public static final ForeignCallDescriptor ARITHMETIC_FREM = new ForeignCallDescriptor("arithmeticFrem", float.class, float.class, float.class); public static final ForeignCallDescriptor ARITHMETIC_DREM = new ForeignCallDescriptor("arithmeticDrem", double.class, double.class, double.class); protected Backend(Providers providers) { this.providers = providers; + this.codeInstallationTaskFactories = new ArrayList<>(); + } + + public synchronized void addCodeInstallationTask(CodeInstallationTaskFactory factory) { + this.codeInstallationTaskFactories.add(factory); } public Providers getProviders() { @@ -113,7 +119,13 @@ public abstract class Backend implements TargetProvider, ValueKindFactory translateToCallerRegisters(Set calleeRegisters); + public abstract EconomicSet translateToCallerRegisters(EconomicSet calleeRegisters); /** * Gets the compilation id for a given {@link ResolvedJavaMethod}. Returns @@ -231,4 +278,38 @@ public abstract class Backend implements TargetProvider, ValueKindFactory createHandlers(OptionValues options) { + return Arrays.asList(new DebugDumpHandler() { + @Override + public void dump(DebugContext ignore, Object object, String format, Object... arguments) { + dumpOutput.format("Dumping %s with label \"%s\"%n", object, String.format(format, arguments)); + } + }, new DebugVerifyHandler() { + @Override + public void verify(DebugContext ignore, Object object, String format, Object... args) { + verifyOutput.format("Verifying %s with label \"%s\"%n", object, String.format(format, args)); + } + }); + } + }; + + DebugContext openDebugContext(OptionValues options) { + return DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, new PrintStream(logOutput), Collections.singletonList(handlers)); + + } + } + + @Test + public void testDisabledScopes() { + OptionValues options = new OptionValues(EconomicMap.create()); + DebugContextSetup setup = new DebugContextSetup(); + try (DebugContext debug = setup.openDebugContext(options); + DebugContext.Scope d = debug.scope("TestDisabledScoping")) { + for (int level = DebugContext.BASIC_LEVEL; level <= DebugContext.VERY_DETAILED_LEVEL; level++) { + debug.dump(level, "an object", "at level %d", level); + debug.verify("an object", "at level %d", level); + debug.log(level, "log statement at level %d", level); + } + } + String log = setup.logOutput.toString(); + String dumpOutput = setup.dumpOutput.toString(); + String verifyOutput = setup.verifyOutput.toString(); + Assert.assertTrue(log, log.isEmpty()); + Assert.assertTrue(dumpOutput, dumpOutput.isEmpty()); + Assert.assertTrue(verifyOutput, verifyOutput.isEmpty()); + } + + @Test + public void testDumping() { + for (int level = DebugContext.BASIC_LEVEL; level <= DebugContext.VERY_DETAILED_LEVEL; level++) { + OptionValues options = new OptionValues(EconomicMap.create()); + options = new OptionValues(options, DebugOptions.Dump, "Scope" + level + ":" + level); + DebugContextSetup setup = new DebugContextSetup(); + try (DebugContext debug = setup.openDebugContext(options); + DebugContext.Scope s0 = debug.scope("TestDumping")) { + try (DebugContext.Scope s1 = debug.scope("Scope1")) { + try (DebugContext.Scope s2 = debug.scope("Scope2")) { + try (DebugContext.Scope s3 = debug.scope("Scope3")) { + try (DebugContext.Scope s4 = debug.scope("Scope4")) { + try (DebugContext.Scope s5 = debug.scope("Scope5")) { + debug.dump(level, "an object", "at level %d", level); + } + } + } + } + } + + } + + String expect = String.format("Dumping an object with label \"at level %d\"%n", level); + String dump = setup.dumpOutput.toString(); + Assert.assertEquals(expect, dump); + } + } + + @Test + public void testLogging() throws IOException { + OptionValues options = new OptionValues(EconomicMap.create()); + options = new OptionValues(options, DebugOptions.Log, ":5"); + DebugContextSetup setup = new DebugContextSetup(); + try (DebugContext debug = setup.openDebugContext(options)) { + for (int level = DebugContext.BASIC_LEVEL; level <= DebugContext.VERY_DETAILED_LEVEL; level++) { + try (DebugContext.Scope s0 = debug.scope("TestLogging")) { + debug.log(level, "log statement at level %d", level); + try (DebugContext.Scope s1 = debug.scope("Level1")) { + debug.log(level, "log statement at level %d", level); + try (DebugContext.Scope s2 = debug.scope("Level2")) { + debug.log(level, "log statement at level %d", level); + try (DebugContext.Scope s3 = debug.scope("Level3")) { + debug.log(level, "log statement at level %d", level); + try (DebugContext.Scope s4 = debug.scope("Level4")) { + debug.log(level, "log statement at level %d", level); + try (DebugContext.Scope s5 = debug.scope("Level5")) { + debug.log(level, "log statement at level %d", level); + } + } + } + } + } + } + } + } + DataInputStream in = new DataInputStream(getClass().getResourceAsStream(getClass().getSimpleName() + ".testLogging.input")); + byte[] buf = new byte[in.available()]; + in.readFully(buf); + String threadLabel = "[thread:" + Thread.currentThread().getId() + "]"; + String expect = new String(buf).replace("[thread:1]", threadLabel); + + String log = setup.logOutput.toString(); + Assert.assertEquals(expect, log); + } + + @Test + public void testEnabledSandbox() { + EconomicMap, Object> map = EconomicMap.create(); + // Configure with an option that enables scopes + map.put(DebugOptions.DumpOnError, true); + OptionValues options = new OptionValues(map); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DebugContext debug = DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, new PrintStream(baos), DebugHandlersFactory.LOADER); + Exception e = new Exception("testEnabledSandbox"); + String scopeName = ""; + try { + try (DebugContext.Scope d = debug.sandbox("TestExceptionHandling", debug.getConfig())) { + scopeName = d.getQualifiedName(); + throw e; + } catch (Throwable t) { + assert e == t; + debug.handle(t); + } + } catch (Throwable t) { + // The exception object should propagate all the way out through + // a enabled sandbox scope + Assert.assertEquals(e, t); + } + String logged = baos.toString(); + String expected = String.format("Exception raised in scope %s: %s", scopeName, e); + String line = "-------------------------------------------------------"; + Assert.assertTrue(String.format("Could not find \"%s\" in content between lines below:%n%s%n%s%s", expected, line, logged, line), logged.contains(expected)); + } + + @Test + public void testDisabledSandbox() { + EconomicMap, Object> map = EconomicMap.create(); + // Configure with an option that enables scopes + map.put(DebugOptions.DumpOnError, true); + OptionValues options = new OptionValues(map); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DebugContext debug = DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, new PrintStream(baos), DebugHandlersFactory.LOADER); + Exception e = new Exception("testDisabledSandbox"); + try { + // Test a disabled sandbox scope + try (DebugContext.Scope d = debug.sandbox("TestExceptionHandling", null)) { + throw e; + } catch (Throwable t) { + assert e == t; + debug.handle(t); + } + } catch (Throwable t) { + // The exception object should propagate all the way out through + // a disabled sandbox scope + Assert.assertEquals(e, t); + } + String logged = baos.toString(); + Assert.assertTrue(logged, logged.isEmpty()); + } + + /** + * Tests that using a {@link DebugContext} on a thread other than the one on which it was + * created causes an assertion failure. + */ + @Test + public void testInvariantChecking() throws InterruptedException { + Assume.assumeTrue(Assertions.assertionsEnabled()); + EconomicMap, Object> map = EconomicMap.create(); + // Configure with an option that enables counters + map.put(DebugOptions.Counters, ""); + OptionValues options = new OptionValues(map); + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); + CounterKey counter = DebugContext.counter("DebugContextTestCounter"); + AssertionError[] result = {null}; + Thread thread = new Thread() { + + @Override + public void run() { + try { + counter.add(debug, 1); + } catch (AssertionError e) { + result[0] = e; + } + } + }; + thread.start(); + thread.join(); + + Assert.assertNotNull("Expected thread to throw AssertionError", result[0]); + } + + @Test + public void testDisableIntercept() { + EconomicMap, Object> map = EconomicMap.create(); + // Configure with an option that enables scopes + map.put(DebugOptions.DumpOnError, true); + OptionValues options = new OptionValues(map); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DebugContext debug = DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, new PrintStream(baos), DebugHandlersFactory.LOADER); + Exception e = new Exception(); + try { + try (DebugCloseable disabled = debug.disableIntercept(); Scope s1 = debug.scope("ScopeWithDisabledIntercept")) { + try (Scope s2 = debug.scope("InnerScopeInheritsDisabledIntercept")) { + throw e; + } + } catch (Throwable t) { + assert e == t; + debug.handle(t); + } + } catch (Throwable t) { + // The exception object should propagate all the way out through + // an intercept disabled scope + Assert.assertEquals(e, t); + } + String logged = baos.toString(); + Assert.assertEquals("Exception should not have been intercepted", "", logged); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.testLogging.input b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.testLogging.input new file mode 100644 index 00000000000..26cd3f9f4e6 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.testLogging.input @@ -0,0 +1,61 @@ +[thread:1] scope: main + [thread:1] scope: main.TestLogging + log statement at level 1 + [thread:1] scope: main.TestLogging.Level1 + log statement at level 1 + [thread:1] scope: main.TestLogging.Level1.Level2 + log statement at level 1 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3 + log statement at level 1 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4 + log statement at level 1 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4.Level5 + log statement at level 1 + [thread:1] scope: main.TestLogging + log statement at level 2 + [thread:1] scope: main.TestLogging.Level1 + log statement at level 2 + [thread:1] scope: main.TestLogging.Level1.Level2 + log statement at level 2 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3 + log statement at level 2 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4 + log statement at level 2 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4.Level5 + log statement at level 2 + [thread:1] scope: main.TestLogging + log statement at level 3 + [thread:1] scope: main.TestLogging.Level1 + log statement at level 3 + [thread:1] scope: main.TestLogging.Level1.Level2 + log statement at level 3 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3 + log statement at level 3 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4 + log statement at level 3 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4.Level5 + log statement at level 3 + [thread:1] scope: main.TestLogging + log statement at level 4 + [thread:1] scope: main.TestLogging.Level1 + log statement at level 4 + [thread:1] scope: main.TestLogging.Level1.Level2 + log statement at level 4 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3 + log statement at level 4 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4 + log statement at level 4 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4.Level5 + log statement at level 4 + [thread:1] scope: main.TestLogging + log statement at level 5 + [thread:1] scope: main.TestLogging.Level1 + log statement at level 5 + [thread:1] scope: main.TestLogging.Level1.Level2 + log statement at level 5 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3 + log statement at level 5 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4 + log statement at level 5 + [thread:1] scope: main.TestLogging.Level1.Level2.Level3.Level4.Level5 + log statement at level 5 diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugHistogramTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugHistogramTest.java deleted file mode 100644 index a6fe2fdf525..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugHistogramTest.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug.test; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; - -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugHistogram; -import org.graalvm.compiler.debug.internal.DebugHistogramAsciiPrinter; -import org.graalvm.compiler.debug.internal.DebugHistogramRPrinter; - -public class DebugHistogramTest { - - @Test - public void testEmptyHistogram() { - DebugHistogram histogram = Debug.createHistogram("TestHistogram"); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - - new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram); - String line = outputStream.toString().split("\r?\n")[0]; - Assert.assertEquals("TestHistogram is empty.", line); - - outputStream.reset(); - new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram); - Assert.assertEquals("", outputStream.toString()); - } - - @Test - public void testSingleEntryHistogram() { - DebugHistogram histogram = Debug.createHistogram("TestHistogram"); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - histogram.add(new Integer(1)); - histogram.add(new Integer(1)); - new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram); - String[] lines = outputStream.toString().split("\r?\n"); - // @formatter:off - String[] expected = { - "TestHistogram has 1 unique elements and 2 total elements:", - "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", - "| 1 | 2 | ==================================================================================================== |", - "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------" - }; - // @formatter:on - Assert.assertArrayEquals(expected, lines); - - outputStream.reset(); - new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram); - lines = outputStream.toString().split("\r?\n"); - // @formatter:off - expected = new String[] { - "TestHistogram <- c(2);", - "names(TestHistogram) <- c(\"1\");" - }; - // @formatter:on - Assert.assertArrayEquals(expected, lines); - } - - @Test - public void testMultipleEntryHistogram() { - DebugHistogram histogram = Debug.createHistogram("TestHistogram"); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - histogram.add(new Integer(1)); - histogram.add(new Integer(2)); - histogram.add(new Integer(2)); - new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram); - String[] lines = outputStream.toString().split("\r?\n"); - // @formatter:off - String[] expected = new String[] { - "TestHistogram has 2 unique elements and 3 total elements:", - "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------", - "| 2 | 2 | ==================================================================================================== |", - "| 1 | 1 | ================================================== |", - "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------" - }; - // @formatter:on - Assert.assertArrayEquals(expected, lines); - - outputStream.reset(); - new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram); - lines = outputStream.toString().split("\r?\n"); - // @formatter:off - expected = new String[] { - "TestHistogram <- c(2, 1);", - "names(TestHistogram) <- c(\"2\", \"1\");" - }; - // @formatter:on - Assert.assertArrayEquals(expected, lines); - } - - @Test - public void testTooLongValueString() { - DebugHistogram histogram = Debug.createHistogram("TestHistogram"); - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - histogram.add("MyCustomValue"); - new DebugHistogramAsciiPrinter(new PrintStream(outputStream), Integer.MAX_VALUE, 10, 10, 1).print(histogram); - String[] lines = outputStream.toString().split("\r?\n"); - Assert.assertEquals(4, lines.length); - Assert.assertEquals("TestHistogram has 1 unique elements and 1 total elements:", lines[0]); - Assert.assertEquals("----------------------------------------", lines[1]); - Assert.assertEquals("| MyCusto... | 1 | ========== |", lines[2]); - Assert.assertEquals("----------------------------------------", lines[3]); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugTimerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugTimerTest.java deleted file mode 100644 index 42b4eee5887..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugTimerTest.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug.test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.lang.management.ThreadMXBean; - -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugConfigScope; -import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.Management; - -@SuppressWarnings("try") -public class DebugTimerTest { - - private static final ThreadMXBean threadMXBean = Management.getThreadMXBean(); - - @Before - public void checkCapabilities() { - Assume.assumeTrue("skipping management interface test", threadMXBean.isCurrentThreadCpuTimeSupported()); - } - - /** - * Actively spins the current thread for at least a given number of milliseconds in such a way - * that timers for the current thread keep ticking over. - * - * @return the number of milliseconds actually spent spinning which is guaranteed to be >= - * {@code ms} - */ - private static long spin(long ms) { - long start = threadMXBean.getCurrentThreadCpuTime(); - do { - long durationMS = (threadMXBean.getCurrentThreadCpuTime() - start) / 1000; - if (durationMS >= ms) { - return durationMS; - } - } while (true); - } - - @Test - public void test1() { - DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, false, null, null, System.out); - try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) { - - DebugTimer timerA = Debug.timer("TimerA"); - DebugTimer timerB = Debug.timer("TimerB"); - - long spinA; - long spinB; - - try (DebugCloseable a1 = timerA.start()) { - spinA = spin(50); - try (DebugCloseable b1 = timerB.start()) { - spinB = spin(50); - } - } - - Assert.assertTrue(timerB.getCurrentValue() < timerA.getCurrentValue()); - if (timerA.getFlat() != null && timerB.getFlat() != null) { - assertTrue(spinB >= spinA || timerB.getFlat().getCurrentValue() < timerA.getFlat().getCurrentValue()); - assertEquals(timerA.getFlat().getCurrentValue(), timerA.getCurrentValue() - timerB.getFlat().getCurrentValue(), 10D); - } - } - } - - @Test - public void test2() { - DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, false, null, null, System.out); - try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) { - DebugTimer timerC = Debug.timer("TimerC"); - try (DebugCloseable c1 = timerC.start()) { - spin(50); - try (DebugCloseable c2 = timerC.start()) { - spin(50); - try (DebugCloseable c3 = timerC.start()) { - spin(50); - try (DebugCloseable c4 = timerC.start()) { - spin(50); - try (DebugCloseable c5 = timerC.start()) { - spin(50); - } - } - } - } - } - if (timerC.getFlat() != null) { - assertEquals(timerC.getFlat().getCurrentValue(), timerC.getCurrentValue()); - } - } - } - - @Test - public void test3() { - DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, false, null, null, System.out); - try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) { - - DebugTimer timerD = Debug.timer("TimerD"); - DebugTimer timerE = Debug.timer("TimerE"); - - long spinD1; - long spinE; - - try (DebugCloseable d1 = timerD.start()) { - spinD1 = spin(50); - try (DebugCloseable e1 = timerE.start()) { - spinE = spin(50); - try (DebugCloseable d2 = timerD.start()) { - spin(50); - try (DebugCloseable d3 = timerD.start()) { - spin(50); - } - } - } - } - - Assert.assertTrue(timerE.getCurrentValue() < timerD.getCurrentValue()); - if (timerD.getFlat() != null && timerE.getFlat() != null) { - assertTrue(spinE >= spinD1 || timerE.getFlat().getCurrentValue() < timerD.getFlat().getCurrentValue()); - assertEquals(timerD.getFlat().getCurrentValue(), timerD.getCurrentValue() - timerE.getFlat().getCurrentValue(), 10D); - } - } - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java new file mode 100644 index 00000000000..b03fc348815 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug.test; + +import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM; +import static org.graalvm.compiler.debug.DebugContext.NO_CONFIG_CUSTOMIZERS; +import static org.graalvm.compiler.debug.DebugContext.NO_DESCRIPTION; +import static org.graalvm.compiler.debug.DebugContext.NO_GLOBAL_METRIC_VALUES; +import static org.junit.Assert.assertEquals; + +import java.lang.management.ThreadMXBean; + +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugOptions; +import org.graalvm.compiler.debug.Management; +import org.graalvm.compiler.debug.TimerKey; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; + +@SuppressWarnings("try") +public class TimerKeyTest { + + @Before + public void checkCapabilities() { + try { + ThreadMXBean threadMXBean = Management.getThreadMXBean(); + Assume.assumeTrue("skipping management interface test", threadMXBean.isCurrentThreadCpuTimeSupported()); + } catch (LinkageError err) { + Assume.assumeNoException("Cannot run without java.management JDK9 module", err); + } + } + + /** + * Actively spins the current thread for at least a given number of milliseconds in such a way + * that timers for the current thread keep ticking over. + * + * @return the number of milliseconds actually spent spinning which is guaranteed to be >= + * {@code ms} + */ + private static long spin(long ms) { + ThreadMXBean threadMXBean = Management.getThreadMXBean(); + long start = threadMXBean.getCurrentThreadCpuTime(); + do { + long durationMS = (threadMXBean.getCurrentThreadCpuTime() - start) / 1000; + if (durationMS >= ms) { + return durationMS; + } + } while (true); + } + + /** + * Asserts that a timer replied recursively without any other interleaving timers has the same + * flat and accumulated times. + */ + @Test + public void test2() { + EconomicMap, Object> map = EconomicMap.create(); + map.put(DebugOptions.Time, ""); + OptionValues options = new OptionValues(map); + DebugContext debug = DebugContext.create(options, NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, NO_CONFIG_CUSTOMIZERS); + + TimerKey timerC = DebugContext.timer("TimerC"); + try (DebugCloseable c1 = timerC.start(debug)) { + spin(50); + try (DebugCloseable c2 = timerC.start(debug)) { + spin(50); + try (DebugCloseable c3 = timerC.start(debug)) { + spin(50); + try (DebugCloseable c4 = timerC.start(debug)) { + spin(50); + try (DebugCloseable c5 = timerC.start(debug)) { + spin(50); + } + } + } + } + } + if (timerC.getFlat() != null) { + assertEquals(timerC.getFlat().getCurrentValue(debug), timerC.getCurrentValue(debug)); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValue.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/AbstractKey.java similarity index 56% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValue.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/AbstractKey.java index c0bba2346ec..280065ecb88 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValue.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/AbstractKey.java @@ -20,50 +20,61 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.debug.internal; +package org.graalvm.compiler.debug; /** - * A name and index for a value managed in a thread local value map. All access to the value is made - * via a {@link DebugValue} instance. + * A name and index for a metric value. */ -public abstract class DebugValue implements Comparable { +abstract class AbstractKey implements MetricKey { - private final String name; + private final String nameFormat; + private final Object nameArg1; + private final Object nameArg2; + + private String name; private int index; - private boolean conditional; + private String doc; - protected DebugValue(String name, boolean conditional) { - this.name = name; + protected AbstractKey(String nameFormat, Object nameArg1, Object nameArg2) { + this.nameFormat = nameFormat; + this.nameArg1 = nameArg1; + this.nameArg2 = nameArg2; this.index = -1; - this.conditional = conditional; } - public long getCurrentValue() { + protected void setDoc(String doc) { + this.doc = doc; + } + + @Override + public String getDoc() { + return doc; + } + + @Override + public String getDocName() { + return getName(); + } + + public long getCurrentValue(DebugContext debug) { ensureInitialized(); - return DebugScope.getInstance().getCurrentValue(index); + return debug.getMetricValue(index); } - protected void setCurrentValue(long l) { + void setCurrentValue(DebugContext debug, long l) { ensureInitialized(); - DebugScope.getInstance().setCurrentValue(index, l); + debug.setMetricValue(index, l); } - public void setConditional(boolean flag) { - conditional = flag; - } - - public boolean isConditional() { - return conditional; - } - - private void ensureInitialized() { + void ensureInitialized() { if (index == -1) { index = KeyRegistry.register(this); } } - protected void addToCurrentValue(long value) { - setCurrentValue(getCurrentValue() + value); + void addToCurrentValue(DebugContext debug, long value) { + ensureInitialized(); + debug.setMetricValue(index, debug.getMetricValue(index) + value); } /** @@ -77,29 +88,20 @@ public abstract class DebugValue implements Comparable { /** * Gets the globally unique name for the value represented by this object. */ + @Override public String getName() { + if (name == null) { + name = createName(nameFormat, nameArg1, nameArg2); + } return name; } - @Override - public int compareTo(DebugValue o) { - return name.compareTo(o.name); + protected String createName(String format, Object arg1, Object arg2) { + return DebugContext.formatDebugName(format, arg1, arg2); } @Override public String toString() { - return name + "@" + index; + return getName() + "@" + index; } - - public abstract String toString(long value); - - /** - * The raw unit of the value (e.g. 'us', 'ms'). Use {@code ""} if there is no unit. - */ - public abstract String rawUnit(); - - /** - * The raw value. - */ - public abstract String toRawString(long value); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/serialize/AbstractSerializer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/AccumulatedKey.java similarity index 60% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/serialize/AbstractSerializer.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/AccumulatedKey.java index 1ed9f8f5172..e21268f7bc3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/serialize/AbstractSerializer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/AccumulatedKey.java @@ -20,43 +20,27 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.salver.serialize; +package org.graalvm.compiler.debug; -import java.io.IOException; +abstract class AccumulatedKey extends AbstractKey { + protected final AbstractKey flat; -import org.graalvm.compiler.salver.writer.DumpWriter; + static final String ACCUMULATED_KEY_SUFFIX = "_Accm"; + static final String FLAT_KEY_SUFFIX = "_Flat"; -public abstract class AbstractSerializer implements Serializer { - - protected DumpWriter writer; - - public AbstractSerializer() { - } - - public AbstractSerializer(DumpWriter writer) { - if (writer != null) { - setWriter(writer); - } + protected AccumulatedKey(AbstractKey flat, String nameFormat, Object nameArg1, Object nameArg2) { + super(nameFormat, nameArg1, nameArg2); + this.flat = flat; } @Override - public DumpWriter getWriter() { - return writer; + protected String createName(String format, Object arg1, Object arg2) { + return super.createName(format, arg1, arg2) + ACCUMULATED_KEY_SUFFIX; } @Override - public void setWriter(DumpWriter writer) { - this.writer = writer; - } - - @Override - public void reset() throws IOException { - } - - @Override - public void flush() throws IOException { - if (writer != null) { - writer.flush(); - } + public String getDocName() { + String name = getName(); + return name.substring(0, name.length() - ACCUMULATED_KEY_SUFFIX.length()); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Assertions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Assertions.java new file mode 100644 index 00000000000..c4acd5ff2a8 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Assertions.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; +import org.graalvm.compiler.options.OptionValues; + +/** + * Utility for query whether assertions are enabled. + */ +public class Assertions { + /** + * Determines if assertions are enabled. Strictly speaking, this may only be true for the + * {@link Assertions} class but we assume assertions are enabled/disabled for Graal as a whole. + */ + public static boolean assertionsEnabled() { + boolean enabled = false; + assert (enabled = true) == true; + return enabled; + } + + /** + * Determines if detailed assertions are enabled. This requires that the normal assertions are + * also enabled. + * + * @param values the current OptionValues that might define a value for DetailAsserts. + */ + public static boolean detailedAssertionsEnabled(OptionValues values) { + return assertionsEnabled() && Options.DetailedAsserts.getValue(values); + } + + // @formatter:off + public static class Options { + + @Option(help = "Enable expensive assertions. (Require normal assertions enabled)", type = OptionType.Debug) + public static final OptionKey DetailedAsserts = new OptionKey<>(true); + + } + // @formatter:on +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CSVUtil.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CSVUtil.java index 5c43ccc9b32..707e463aff6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CSVUtil.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CSVUtil.java @@ -84,7 +84,11 @@ public final class CSVUtil { return out; } - private static Object[] escapeArgs(char separator, char quote, char escape, Object... args) { + public static Object[] escapeArgs(Object... args) { + return escapeArgs(SEPARATOR, QUOTE, ESCAPE, args); + } + + public static Object[] escapeArgs(char separator, char quote, char escape, Object... args) { String separatorStr = String.valueOf(separator); for (int i = 0; i < args.length; i++) { Object obj = args[i]; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/CloseableCounterImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CloseableCounter.java similarity index 73% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/CloseableCounterImpl.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CloseableCounter.java index b3ca4b39ef2..80b1eb1ffcd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/CloseableCounterImpl.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CloseableCounter.java @@ -20,31 +20,36 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.debug.internal; - -import org.graalvm.compiler.debug.DebugCloseable; +package org.graalvm.compiler.debug; /** - * A helper class for DebugValues that can nest and need to split out accumulated and flat values - * for some kind of counter-like measurement. + * A helper class for {@link AbstractKey}s that can nest and need to split out accumulated and flat + * values for some kind of counter-like measurement. */ -abstract class CloseableCounterImpl implements DebugCloseable { +public abstract class CloseableCounter implements DebugCloseable { - protected final CloseableCounterImpl parent; - protected final AccumulatedDebugValue counter; + protected final DebugContext debug; + protected final CloseableCounter parent; + protected final AccumulatedKey counter; protected final long start; protected long nestedAmountToSubtract; - CloseableCounterImpl(CloseableCounterImpl parent, AccumulatedDebugValue counter) { + CloseableCounter(DebugContext debug, CloseableCounter parent, AccumulatedKey counter) { + this.debug = debug; this.parent = parent; this.start = getCounterValue(); this.counter = counter; } + @Override + public DebugContext getDebug() { + return debug; + } + /** * A hook for subclasses. Lets them perform custom operations with the value since the last - * invocation of {@link CloseableCounterImpl#close()} of this accumulated - * {@link CloseableCounterImpl#counter}. + * invocation of {@link CloseableCounter#close()} of this accumulated + * {@link CloseableCounter#counter}. * * @param difference since the last invocation of this counter flat */ @@ -54,8 +59,7 @@ abstract class CloseableCounterImpl implements DebugCloseable { /** * A hook for subclasses. Lets them perform custom operations with the value since the last - * invocation of {@link CloseableCounterImpl#close()} of this flat - * {@link CloseableCounterImpl#counter}. + * invocation of {@link CloseableCounter#close()} of this flat {@link CloseableCounter#counter}. * * @param difference since the last invocation of this counter flat */ @@ -72,7 +76,7 @@ abstract class CloseableCounterImpl implements DebugCloseable { parent.nestedAmountToSubtract += difference; // Look for our counter in an outer scope and fix up // the adjustment to the flat count - CloseableCounterImpl ancestor = parent.parent; + CloseableCounter ancestor = parent.parent; while (ancestor != null) { if (ancestor.counter.getName().equals(counter.getName())) { ancestor.nestedAmountToSubtract -= difference; @@ -83,8 +87,8 @@ abstract class CloseableCounterImpl implements DebugCloseable { } } long flatAmount = difference - nestedAmountToSubtract; - counter.addToCurrentValue(difference); - counter.flat.addToCurrentValue(flatAmount); + counter.addToCurrentValue(debug, difference); + counter.flat.addToCurrentValue(debug, flatAmount); interceptDifferenceAccm(difference); interceptDifferenceFlat(flatAmount); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugValueFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKey.java similarity index 62% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugValueFactory.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKey.java index a97d90e9d91..27318af48a3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugValueFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,19 +22,31 @@ */ package org.graalvm.compiler.debug; -import jdk.vm.ci.meta.ResolvedJavaMethod; - /** - * A factory for creating {@link DebugCounter}s, {@link DebugTimer}s, {@link DebugMemUseTracker}s - * and {@link DebugMethodMetrics}. + * A counter for some value of interest. */ -public interface DebugValueFactory { +public interface CounterKey extends MetricKey { - DebugCounter createCounter(String name, boolean conditional); + /** + * Adds 1 to this counter. + */ + void increment(DebugContext debug); - DebugTimer createTimer(String name, boolean conditional); + /** + * Adds {@code value} to this counter. + */ + void add(DebugContext debug, long value); - DebugMemUseTracker createMemUseTracker(String name, boolean conditional); + /** + * Gets the current value of this counter. + */ + long getCurrentValue(DebugContext debug); - DebugMethodMetrics createMethodMetrics(ResolvedJavaMethod method); + /** + * Determines if this counter is enabled. + */ + boolean isEnabled(DebugContext debug); + + @Override + CounterKey doc(String string); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest5.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKeyImpl.java similarity index 52% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest5.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKeyImpl.java index c294a4037dc..7e942517578 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/debug/MethodMetricsTest5.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKeyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,34 +20,46 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.core.test.debug; +package org.graalvm.compiler.debug; -import org.junit.Test; +import org.graalvm.util.Pair; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.phases.Phase; +class CounterKeyImpl extends AbstractKey implements CounterKey { -public class MethodMetricsTest5 extends MethodMetricsTest { - - @Override - protected Phase additionalPhase() { - return new MethodMetricPhases.CountingDivPhase(); + CounterKeyImpl(String format, Object arg1, Object arg2) { + super(format, arg1, arg2); } @Override - DebugConfig getConfig() { - return overrideGraalDebugConfig(System.out, "MethodMetricsTest$TestApplication.*", "CountingDivPhase"); + public void increment(DebugContext debug) { + add(debug, 1); } @Override - void assertValues() throws Throwable { - assertValues("Divs", new long[]{0, 0, 0, 0, 0, 0, 0, 0, 1, 0}); + public Pair toCSVFormat(long value) { + return Pair.create(String.valueOf(value), ""); } @Override - @Test - public void test() throws Throwable { - super.test(); + public String toHumanReadableFormat(long value) { + return Long.toString(value); } + @Override + public void add(DebugContext debug, long value) { + if (debug.isCounterEnabled(this)) { + addToCurrentValue(debug, value); + } + } + + @Override + public boolean isEnabled(DebugContext debug) { + return debug.isCounterEnabled(this); + } + + @Override + public CounterKey doc(String doc) { + setDoc(doc); + return this; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java deleted file mode 100644 index cd5e7fca7ae..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Debug.java +++ /dev/null @@ -1,1714 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug; - -import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.INTERCEPT; -import static org.graalvm.compiler.debug.DelegatingDebugConfig.Feature.LOG_METHOD; -import static java.util.FormattableFlags.LEFT_JUSTIFY; -import static java.util.FormattableFlags.UPPERCASE; - -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.ConcurrentModificationException; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.TimeUnit; - -import org.graalvm.compiler.debug.DelegatingDebugConfig.Level; -import org.graalvm.compiler.debug.internal.CounterImpl; -import org.graalvm.compiler.debug.internal.DebugHistogramImpl; -import org.graalvm.compiler.debug.internal.DebugScope; -import org.graalvm.compiler.debug.internal.MemUseTrackerImpl; -import org.graalvm.compiler.debug.internal.TimerImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.serviceprovider.GraalServices; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -/** - * Scope based debugging facility. - * - * This facility is {@linkplain #isEnabled() enabled} if any of the following hold when the - * {@link Debug} class is initialized: - *

        - *
      • assertions are enabled for the {@link Debug} class
      • - *
      • {@link Debug#params}{@code .enable} is {@code true}
      • - *
      - */ -public class Debug { - - private static final Params params = new Params(); - - static { - // Load the service providers that may want to modify any of the - // parameters encapsulated by the Initialization class below. - for (DebugInitializationParticipant p : GraalServices.load(DebugInitializationParticipant.class)) { - p.apply(params); - } - } - - /** - * The parameters for configuring the initialization of {@link Debug} class. - */ - public static class Params { - public boolean enable; - public boolean enableMethodFilter; - public boolean enableUnscopedTimers; - public boolean enableUnscopedCounters; - public boolean enableUnscopedMethodMetrics; - public boolean enableUnscopedMemUseTrackers; - public boolean interceptCount; - public boolean interceptTime; - public boolean interceptMem; - } - - @SuppressWarnings("all") - private static boolean initialize() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; - return assertionsEnabled || params.enable || GraalDebugConfig.Options.ForceDebugEnable.getValue(); - } - - private static final boolean ENABLED = initialize(); - - public static boolean isEnabled() { - return ENABLED; - } - - public static boolean isDumpEnabledForMethod() { - if (!ENABLED) { - return false; - } - DebugConfig config = DebugScope.getConfig(); - if (config == null) { - return false; - } - return config.isDumpEnabledForMethod(); - } - - public static final int BASIC_LOG_LEVEL = 1; - public static final int INFO_LOG_LEVEL = 2; - public static final int VERBOSE_LOG_LEVEL = 3; - public static final int DETAILED_LOG_LEVEL = 4; - public static final int VERY_DETAILED_LOG_LEVEL = 5; - - public static boolean isDumpEnabled(int dumpLevel) { - return ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel); - } - - /** - * Determines if verification is enabled in the current method, regardless of the - * {@linkplain Debug#currentScope() current debug scope}. - * - * @see Debug#verify(Object, String) - */ - public static boolean isVerifyEnabledForMethod() { - if (!ENABLED) { - return false; - } - DebugConfig config = DebugScope.getConfig(); - if (config == null) { - return false; - } - return config.isVerifyEnabledForMethod(); - } - - /** - * Determines if verification is enabled in the {@linkplain Debug#currentScope() current debug - * scope}. - * - * @see Debug#verify(Object, String) - */ - public static boolean isVerifyEnabled() { - return ENABLED && DebugScope.getInstance().isVerifyEnabled(); - } - - public static boolean isCountEnabled() { - return ENABLED && DebugScope.getInstance().isCountEnabled(); - } - - public static boolean isTimeEnabled() { - return ENABLED && DebugScope.getInstance().isTimeEnabled(); - } - - public static boolean isMemUseTrackingEnabled() { - return ENABLED && DebugScope.getInstance().isMemUseTrackingEnabled(); - } - - public static boolean isLogEnabledForMethod() { - if (!ENABLED) { - return false; - } - DebugConfig config = DebugScope.getConfig(); - if (config == null) { - return false; - } - return config.isLogEnabledForMethod(); - } - - public static boolean isLogEnabled() { - return isLogEnabled(BASIC_LOG_LEVEL); - } - - public static boolean isLogEnabled(int logLevel) { - return ENABLED && DebugScope.getInstance().isLogEnabled(logLevel); - } - - public static boolean isMethodMeterEnabled() { - return ENABLED && DebugScope.getInstance().isMethodMeterEnabled(); - } - - @SuppressWarnings("unused") - public static Runnable decorateDebugRoot(Runnable runnable, String name, DebugConfig config) { - return runnable; - } - - @SuppressWarnings("unused") - public static Callable decorateDebugRoot(Callable callable, String name, DebugConfig config) { - return callable; - } - - @SuppressWarnings("unused") - public static Runnable decorateScope(Runnable runnable, String name, Object... context) { - return runnable; - } - - @SuppressWarnings("unused") - public static Callable decorateScope(Callable callable, String name, Object... context) { - return callable; - } - - /** - * Gets a string composed of the names in the current nesting of debug - * {@linkplain #scope(Object) scopes} separated by {@code '.'}. - */ - public static String currentScope() { - if (ENABLED) { - return DebugScope.getInstance().getQualifiedName(); - } else { - return ""; - } - } - - /** - * Represents a debug scope entered by {@link Debug#scope(Object)} or - * {@link Debug#sandbox(CharSequence, DebugConfig, Object...)}. Leaving the scope is achieved - * via {@link #close()}. - */ - public interface Scope extends AutoCloseable { - @Override - void close(); - } - - /** - * Creates and enters a new debug scope which will be a child of the current debug scope. - *

      - * It is recommended to use the try-with-resource statement for managing entering and leaving - * debug scopes. For example: - * - *

      -     * try (Scope s = Debug.scope("InliningGraph", inlineeGraph)) {
      -     *     ...
      -     * } catch (Throwable e) {
      -     *     throw Debug.handle(e);
      -     * }
      -     * 
      - * - * The {@code name} argument is subject to the following type based conversion before having - * {@link Object#toString()} called on it: - * - *
      -     *     Type          | Conversion
      -     * ------------------+-----------------
      -     *  java.lang.Class  | arg.getSimpleName()
      -     *                   |
      -     * 
      - * - * @param name the name of the new scope - * @param contextObjects an array of object to be appended to the {@linkplain #context() - * current} debug context - * @throws Throwable used to enforce a catch block. - * @return the scope entered by this method which will be exited when its {@link Scope#close()} - * method is called - */ - public static Scope scope(Object name, Object[] contextObjects) throws Throwable { - if (ENABLED) { - return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, contextObjects); - } else { - return null; - } - } - - /** - * Similar to {@link #scope(Object, Object[])} but without context objects. Therefore the catch - * block can be omitted. - * - * @see #scope(Object, Object[]) - */ - public static Scope scope(Object name) { - if (ENABLED) { - return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null); - } else { - return null; - } - } - - public static Scope methodMetricsScope(Object name, DebugScope.ExtraInfo metaInfo, boolean newId, Object... context) { - if (ENABLED) { - return DebugScope.getInstance().enhanceWithExtraInfo(convertFormatArg(name).toString(), metaInfo, newId, context); - } else { - return null; - } - } - - /** - * @see #scope(Object, Object[]) - * @param context an object to be appended to the {@linkplain #context() current} debug context - */ - public static Scope scope(Object name, Object context) throws Throwable { - if (ENABLED) { - return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context); - } else { - return null; - } - } - - /** - * @see #scope(Object, Object[]) - * @param context1 first object to be appended to the {@linkplain #context() current} debug - * context - * @param context2 second object to be appended to the {@linkplain #context() current} debug - * context - */ - public static Scope scope(Object name, Object context1, Object context2) throws Throwable { - if (ENABLED) { - return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context1, context2); - } else { - return null; - } - } - - /** - * @see #scope(Object, Object[]) - * @param context1 first object to be appended to the {@linkplain #context() current} debug - * context - * @param context2 second object to be appended to the {@linkplain #context() current} debug - * context - * @param context3 third object to be appended to the {@linkplain #context() current} debug - * context - */ - public static Scope scope(Object name, Object context1, Object context2, Object context3) throws Throwable { - if (ENABLED) { - return DebugScope.getInstance().scope(convertFormatArg(name).toString(), null, context1, context2, context3); - } else { - return null; - } - } - - /** - * Creates and enters a new debug scope which will be disjoint from the current debug scope. - *

      - * It is recommended to use the try-with-resource statement for managing entering and leaving - * debug scopes. For example: - * - *

      -     * try (Scope s = Debug.sandbox("CompilingStub", null, stubGraph)) {
      -     *     ...
      -     * } catch (Throwable e) {
      -     *     throw Debug.handle(e);
      -     * }
      -     * 
      - * - * @param name the name of the new scope - * @param config the debug configuration to use for the new scope - * @param context objects to be appended to the {@linkplain #context() current} debug context - * @return the scope entered by this method which will be exited when its {@link Scope#close()} - * method is called - */ - public static Scope sandbox(CharSequence name, DebugConfig config, Object... context) throws Throwable { - if (ENABLED) { - DebugConfig sandboxConfig = config == null ? silentConfig() : config; - return DebugScope.getInstance().scope(name, sandboxConfig, context); - } else { - return null; - } - } - - public static Scope forceLog() throws Throwable { - ArrayList context = new ArrayList<>(); - for (Object obj : context()) { - context.add(obj); - } - return Debug.sandbox("forceLog", new DelegatingDebugConfig().override(Level.LOG, Integer.MAX_VALUE).enable(LOG_METHOD), context.toArray()); - } - - /** - * Opens a scope in which exception {@linkplain DebugConfig#interceptException(Throwable) - * interception} is disabled. It is recommended to use the try-with-resource statement for - * managing entering and leaving such scopes: - * - *
      -     * try (DebugConfigScope s = Debug.disableIntercept()) {
      -     *     ...
      -     * }
      -     * 
      - * - * This is particularly useful to suppress extraneous output in JUnit tests that are expected to - * throw an exception. - */ - public static DebugConfigScope disableIntercept() { - return Debug.setConfig(new DelegatingDebugConfig().disable(INTERCEPT)); - } - - /** - * Handles an exception in the context of the debug scope just exited. The just exited scope - * must have the current scope as its parent which will be the case if the try-with-resource - * pattern recommended by {@link #scope(Object)} and - * {@link #sandbox(CharSequence, DebugConfig, Object...)} is used - * - * @see #scope(Object, Object[]) - * @see #sandbox(CharSequence, DebugConfig, Object...) - */ - public static RuntimeException handle(Throwable exception) { - if (ENABLED) { - return DebugScope.getInstance().handle(exception); - } else { - if (exception instanceof Error) { - throw (Error) exception; - } - if (exception instanceof RuntimeException) { - throw (RuntimeException) exception; - } - throw new RuntimeException(exception); - } - } - - public static void log(String msg) { - log(BASIC_LOG_LEVEL, msg); - } - - /** - * Prints a message to the current debug scope's logging stream if logging is enabled. - * - * @param msg the message to log - */ - public static void log(int logLevel, String msg) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, msg); - } - } - - public static void log(String format, Object arg) { - log(BASIC_LOG_LEVEL, format, arg); - } - - /** - * Prints a message to the current debug scope's logging stream if logging is enabled. - * - * @param format a format string - * @param arg the argument referenced by the format specifiers in {@code format} - */ - public static void log(int logLevel, String format, Object arg) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg); - } - } - - public static void log(String format, int arg) { - log(BASIC_LOG_LEVEL, format, arg); - } - - /** - * Prints a message to the current debug scope's logging stream if logging is enabled. - * - * @param format a format string - * @param arg the argument referenced by the format specifiers in {@code format} - */ - public static void log(int logLevel, String format, int arg) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg); - } - } - - public static void log(String format, Object arg1, Object arg2) { - log(BASIC_LOG_LEVEL, format, arg1, arg2); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, Object arg1, Object arg2) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2); - } - } - - public static void log(String format, int arg1, Object arg2) { - log(BASIC_LOG_LEVEL, format, arg1, arg2); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, int arg1, Object arg2) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2); - } - } - - public static void log(String format, Object arg1, int arg2) { - log(BASIC_LOG_LEVEL, format, arg1, arg2); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, Object arg1, int arg2) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2); - } - } - - public static void log(String format, int arg1, int arg2) { - log(BASIC_LOG_LEVEL, format, arg1, arg2); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, int arg1, int arg2) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2); - } - } - - public static void log(String format, Object arg1, Object arg2, Object arg3) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3); - } - } - - public static void log(String format, int arg1, int arg2, int arg3) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, int arg1, int arg2, int arg3) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3); - } - } - - public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4); - } - } - - public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5); - } - } - - public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6); - } - } - - public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); - } - - public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); - } - - /** - * @see #log(int, String, Object) - */ - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); - } - } - - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); - } - } - - public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); - } - - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); - } - } - - public static void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { - log(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); - } - - public static void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { - if (ENABLED) { - DebugScope.getInstance().log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); - } - } - - public static void logv(String format, Object... args) { - logv(BASIC_LOG_LEVEL, format, args); - } - - /** - * Prints a message to the current debug scope's logging stream. This method must only be called - * if debugging is {@linkplain Debug#isEnabled() enabled} as it incurs allocation at the call - * site. If possible, call one of the other {@code log()} methods in this class that take a - * fixed number of parameters. - * - * @param format a format string - * @param args the arguments referenced by the format specifiers in {@code format} - */ - public static void logv(int logLevel, String format, Object... args) { - if (!ENABLED) { - throw new InternalError("Use of Debug.logv() must be guarded by a test of Debug.isEnabled()"); - } - DebugScope.getInstance().log(logLevel, format, args); - } - - /** - * This override exists to catch cases when {@link #log(String, Object)} is called with one - * argument bound to a varargs method parameter. It will bind to this method instead of the - * single arg variant and produce a deprecation warning instead of silently wrapping the - * Object[] inside of another Object[]. - */ - @Deprecated - public static void log(String format, Object[] args) { - assert false : "shouldn't use this"; - log(BASIC_LOG_LEVEL, format, args); - } - - /** - * This override exists to catch cases when {@link #log(int, String, Object)} is called with one - * argument bound to a varargs method parameter. It will bind to this method instead of the - * single arg variant and produce a deprecation warning instead of silently wrapping the - * Object[] inside of another Object[]. - */ - @Deprecated - public static void log(int logLevel, String format, Object[] args) { - assert false : "shouldn't use this"; - logv(logLevel, format, args); - } - - public static void dump(int dumpLevel, Object object, String msg) { - if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) { - DebugScope.getInstance().dump(dumpLevel, object, msg); - } - } - - public static void dump(int dumpLevel, Object object, String format, Object arg) { - if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) { - DebugScope.getInstance().dump(dumpLevel, object, format, arg); - } - } - - public static void dump(int dumpLevel, Object object, String format, Object arg1, Object arg2) { - if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) { - DebugScope.getInstance().dump(dumpLevel, object, format, arg1, arg2); - } - } - - public static void dump(int dumpLevel, Object object, String format, Object arg1, Object arg2, Object arg3) { - if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) { - DebugScope.getInstance().dump(dumpLevel, object, format, arg1, arg2, arg3); - } - } - - /** - * This override exists to catch cases when {@link #dump(int, Object, String, Object)} is called - * with one argument bound to a varargs method parameter. It will bind to this method instead of - * the single arg variant and produce a deprecation warning instead of silently wrapping the - * Object[] inside of another Object[]. - */ - @Deprecated - public static void dump(int dumpLevel, Object object, String format, Object[] args) { - assert false : "shouldn't use this"; - if (ENABLED && DebugScope.getInstance().isDumpEnabled(dumpLevel)) { - DebugScope.getInstance().dump(dumpLevel, object, format, args); - } - } - - /** - * Calls all {@link DebugVerifyHandler}s in the current {@linkplain DebugScope#getConfig() - * config} to perform verification on a given object. - * - * @param object object to verify - * @param message description of verification context - * - * @see DebugVerifyHandler#verify(Object, String) - */ - public static void verify(Object object, String message) { - if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) { - DebugScope.getInstance().verify(object, message); - } - } - - /** - * Calls all {@link DebugVerifyHandler}s in the current {@linkplain DebugScope#getConfig() - * config} to perform verification on a given object. - * - * @param object object to verify - * @param format a format string for the description of the verification context - * @param arg the argument referenced by the format specifiers in {@code format} - * - * @see DebugVerifyHandler#verify(Object, String) - */ - public static void verify(Object object, String format, Object arg) { - if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) { - DebugScope.getInstance().verify(object, format, arg); - } - } - - /** - * This override exists to catch cases when {@link #verify(Object, String, Object)} is called - * with one argument bound to a varargs method parameter. It will bind to this method instead of - * the single arg variant and produce a deprecation warning instead of silently wrapping the - * Object[] inside of another Object[]. - */ - @Deprecated - public static void verify(Object object, String format, Object[] args) { - assert false : "shouldn't use this"; - if (ENABLED && DebugScope.getInstance().isVerifyEnabled()) { - DebugScope.getInstance().verify(object, format, args); - } - } - - /** - * Opens a new indentation level (by adding some spaces) based on the current indentation level. - * This should be used in a {@linkplain Indent try-with-resources} pattern. - * - * @return an object that reverts to the current indentation level when - * {@linkplain Indent#close() closed} or null if debugging is disabled - * @see #logAndIndent(int, String) - * @see #logAndIndent(int, String, Object) - */ - public static Indent indent() { - if (ENABLED) { - DebugScope scope = DebugScope.getInstance(); - return scope.pushIndentLogger(); - } - return null; - } - - public static Indent logAndIndent(String msg) { - return logAndIndent(BASIC_LOG_LEVEL, msg); - } - - /** - * A convenience function which combines {@link #log(String)} and {@link #indent()}. - * - * @param msg the message to log - * @return an object that reverts to the current indentation level when - * {@linkplain Indent#close() closed} or null if debugging is disabled - */ - public static Indent logAndIndent(int logLevel, String msg) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, msg); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg); - } - - /** - * A convenience function which combines {@link #log(String, Object)} and {@link #indent()}. - * - * @param format a format string - * @param arg the argument referenced by the format specifiers in {@code format} - * @return an object that reverts to the current indentation level when - * {@linkplain Indent#close() closed} or null if debugging is disabled - */ - public static Indent logAndIndent(int logLevel, String format, Object arg) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg); - } - return null; - } - - public static Indent logAndIndent(String format, int arg) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg); - } - - /** - * A convenience function which combines {@link #log(String, Object)} and {@link #indent()}. - * - * @param format a format string - * @param arg the argument referenced by the format specifiers in {@code format} - * @return an object that reverts to the current indentation level when - * {@linkplain Indent#close() closed} or null if debugging is disabled - */ - public static Indent logAndIndent(int logLevel, String format, int arg) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg); - } - return null; - } - - public static Indent logAndIndent(String format, int arg1, Object arg2) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, int arg1, Object arg2) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg1, int arg2) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, Object arg1, int arg2) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2); - } - return null; - } - - public static Indent logAndIndent(String format, int arg1, int arg2) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, int arg1, int arg2) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg1, Object arg2) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3); - } - return null; - } - - public static Indent logAndIndent(String format, int arg1, int arg2, int arg3) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, int arg1, int arg2, int arg3) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg1, int arg2, int arg3) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, Object arg1, int arg2, int arg3) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3, arg4); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3, arg4, arg5); - } - return null; - } - - public static Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { - return logAndIndent(BASIC_LOG_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); - } - - /** - * @see #logAndIndent(int, String, Object) - */ - public static Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { - if (ENABLED && Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6); - } - return null; - } - - /** - * A convenience function which combines {@link #logv(int, String, Object...)} and - * {@link #indent()}. - * - * @param format a format string - * @param args the arguments referenced by the format specifiers in {@code format} - * @return an object that reverts to the current indentation level when - * {@linkplain Indent#close() closed} or null if debugging is disabled - */ - public static Indent logvAndIndent(int logLevel, String format, Object... args) { - if (ENABLED) { - if (Debug.isLogEnabled(logLevel)) { - return logvAndIndentInternal(logLevel, format, args); - } - return null; - } - throw new InternalError("Use of Debug.logvAndIndent() must be guarded by a test of Debug.isEnabled()"); - } - - private static Indent logvAndIndentInternal(int logLevel, String format, Object... args) { - assert ENABLED && Debug.isLogEnabled(logLevel) : "must have checked Debug.isLogEnabled()"; - DebugScope scope = DebugScope.getInstance(); - scope.log(logLevel, format, args); - return scope.pushIndentLogger(); - } - - /** - * This override exists to catch cases when {@link #logAndIndent(String, Object)} is called with - * one argument bound to a varargs method parameter. It will bind to this method instead of the - * single arg variant and produce a deprecation warning instead of silently wrapping the - * Object[] inside of another Object[]. - */ - @Deprecated - public static void logAndIndent(String format, Object[] args) { - assert false : "shouldn't use this"; - logAndIndent(BASIC_LOG_LEVEL, format, args); - } - - /** - * This override exists to catch cases when {@link #logAndIndent(int, String, Object)} is called - * with one argument bound to a varargs method parameter. It will bind to this method instead of - * the single arg variant and produce a deprecation warning instead of silently wrapping the - * Object[] inside of another Object[]. - */ - @Deprecated - public static void logAndIndent(int logLevel, String format, Object[] args) { - assert false : "shouldn't use this"; - logvAndIndent(logLevel, format, args); - } - - public static Iterable context() { - if (ENABLED) { - return DebugScope.getInstance().getCurrentContext(); - } else { - return Collections.emptyList(); - } - } - - @SuppressWarnings("unchecked") - public static List contextSnapshot(Class clazz) { - if (ENABLED) { - List result = new ArrayList<>(); - for (Object o : context()) { - if (clazz.isInstance(o)) { - result.add((T) o); - } - } - return result; - } else { - return Collections.emptyList(); - } - } - - /** - * Searches the current debug scope, bottom up, for a context object that is an instance of a - * given type. The first such object found is returned. - */ - @SuppressWarnings("unchecked") - public static T contextLookup(Class clazz) { - if (ENABLED) { - for (Object o : context()) { - if (clazz.isInstance(o)) { - return ((T) o); - } - } - } - return null; - } - - /** - * Creates a {@linkplain DebugMemUseTracker memory use tracker} that is enabled iff debugging is - * {@linkplain #isEnabled() enabled}. - *

      - * A disabled tracker has virtually no overhead. - */ - public static DebugMemUseTracker memUseTracker(CharSequence name) { - if (!isUnconditionalMemUseTrackingEnabled && !ENABLED) { - return VOID_MEM_USE_TRACKER; - } - return createMemUseTracker("%s", name, null); - } - - /** - * Creates a debug memory use tracker. Invoking this method is equivalent to: - * - *

      -     * Debug.memUseTracker(format, arg, null)
      -     * 
      - * - * except that the string formatting only happens if mem tracking is enabled. - * - * @see #counter(String, Object, Object) - */ - public static DebugMemUseTracker memUseTracker(String format, Object arg) { - if (!isUnconditionalMemUseTrackingEnabled && !ENABLED) { - return VOID_MEM_USE_TRACKER; - } - return createMemUseTracker(format, arg, null); - } - - /** - * Creates a debug memory use tracker. Invoking this method is equivalent to: - * - *
      -     * Debug.memUseTracker(String.format(format, arg1, arg2))
      -     * 
      - * - * except that the string formatting only happens if memory use tracking is enabled. In - * addition, each argument is subject to the following type based conversion before being passed - * as an argument to {@link String#format(String, Object...)}: - * - *
      -     *     Type          | Conversion
      -     * ------------------+-----------------
      -     *  java.lang.Class  | arg.getSimpleName()
      -     *                   |
      -     * 
      - * - * @see #memUseTracker(CharSequence) - */ - public static DebugMemUseTracker memUseTracker(String format, Object arg1, Object arg2) { - if (!isUnconditionalMemUseTrackingEnabled && !ENABLED) { - return VOID_MEM_USE_TRACKER; - } - return createMemUseTracker(format, arg1, arg2); - } - - private static DebugMemUseTracker createMemUseTracker(String format, Object arg1, Object arg2) { - String name = formatDebugName(format, arg1, arg2); - return DebugValueFactory.createMemUseTracker(name, !isUnconditionalMemUseTrackingEnabled); - } - - /** - * Creates a {@linkplain DebugCounter counter} that is enabled iff debugging is - * {@linkplain #isEnabled() enabled} or the system property whose name is formed by adding - * {@value #ENABLE_COUNTER_PROPERTY_NAME_PREFIX} to {@code name} is - * {@linkplain Boolean#getBoolean(String) true}. If the latter condition is true, then the - * returned counter is {@linkplain DebugCounter#isConditional() unconditional} otherwise it is - * conditional. - *

      - * A disabled counter has virtually no overhead. - */ - public static DebugCounter counter(CharSequence name) { - if (!areUnconditionalCountersEnabled() && !ENABLED) { - return VOID_COUNTER; - } - return createCounter("%s", name, null); - } - - /** - * Creates a {@link DebugMethodMetrics metric} that is enabled iff debugging is - * {@link #isEnabled() enabled}. - */ - public static DebugMethodMetrics methodMetrics(ResolvedJavaMethod method) { - if (isMethodMeterEnabled() && method != null) { - return MethodMetricsImpl.getMethodMetrics(method); - } - return VOID_MM; - } - - public static String applyFormattingFlagsAndWidth(String s, int flags, int width) { - if (flags == 0 && width < 0) { - return s; - } - StringBuilder sb = new StringBuilder(s); - - // apply width and justification - int len = sb.length(); - if (len < width) { - for (int i = 0; i < width - len; i++) { - if ((flags & LEFT_JUSTIFY) == LEFT_JUSTIFY) { - sb.append(' '); - } else { - sb.insert(0, ' '); - } - } - } - - String res = sb.toString(); - if ((flags & UPPERCASE) == UPPERCASE) { - res = res.toUpperCase(); - } - return res; - } - - /** - * Creates a debug counter. Invoking this method is equivalent to: - * - *

      -     * Debug.counter(format, arg, null)
      -     * 
      - * - * except that the string formatting only happens if count is enabled. - * - * @see #counter(String, Object, Object) - */ - public static DebugCounter counter(String format, Object arg) { - if (!areUnconditionalCountersEnabled() && !ENABLED) { - return VOID_COUNTER; - } - return createCounter(format, arg, null); - } - - /** - * Creates a debug counter. Invoking this method is equivalent to: - * - *
      -     * Debug.counter(String.format(format, arg1, arg2))
      -     * 
      - * - * except that the string formatting only happens if count is enabled. In addition, each - * argument is subject to the following type based conversion before being passed as an argument - * to {@link String#format(String, Object...)}: - * - *
      -     *     Type          | Conversion
      -     * ------------------+-----------------
      -     *  java.lang.Class  | arg.getSimpleName()
      -     *                   |
      -     * 
      - * - * @see #counter(CharSequence) - */ - public static DebugCounter counter(String format, Object arg1, Object arg2) { - if (!areUnconditionalCountersEnabled() && !ENABLED) { - return VOID_COUNTER; - } - return createCounter(format, arg1, arg2); - } - - private static DebugCounter createCounter(String format, Object arg1, Object arg2) { - String name = formatDebugName(format, arg1, arg2); - boolean conditional = enabledCounters == null || !findMatch(enabledCounters, enabledCountersSubstrings, name); - if (!ENABLED && conditional) { - return VOID_COUNTER; - } - return DebugValueFactory.createCounter(name, conditional); - } - - /** - * Changes the debug configuration for the current thread. - * - * @param config new configuration to use for the current thread - * @return an object that when {@linkplain DebugConfigScope#close() closed} will restore the - * debug configuration for the current thread to what it was before this method was - * called - */ - public static DebugConfigScope setConfig(DebugConfig config) { - if (ENABLED) { - return new DebugConfigScope(config); - } else { - return null; - } - } - - /** - * Creates an object for counting value frequencies. - */ - public static DebugHistogram createHistogram(String name) { - return new DebugHistogramImpl(name); - } - - public static DebugConfig silentConfig() { - return fixedConfig(0, 0, false, false, false, false, false, Collections. emptyList(), Collections. emptyList(), null); - } - - public static DebugConfig fixedConfig(final int logLevel, final int dumpLevel, final boolean isCountEnabled, final boolean isMemUseTrackingEnabled, final boolean isTimerEnabled, - final boolean isVerifyEnabled, final boolean isMMEnabled, final Collection dumpHandlers, final Collection verifyHandlers, - final PrintStream output) { - return new DebugConfig() { - - @Override - public int getLogLevel() { - return logLevel; - } - - @Override - public boolean isLogEnabledForMethod() { - return logLevel > 0; - } - - @Override - public boolean isCountEnabled() { - return isCountEnabled; - } - - @Override - public boolean isMemUseTrackingEnabled() { - return isMemUseTrackingEnabled; - } - - @Override - public int getDumpLevel() { - return dumpLevel; - } - - @Override - public boolean isDumpEnabledForMethod() { - return dumpLevel > 0; - } - - @Override - public boolean isVerifyEnabled() { - return isVerifyEnabled; - } - - @Override - public boolean isVerifyEnabledForMethod() { - return isVerifyEnabled; - } - - @Override - public boolean isMethodMeterEnabled() { - return isMMEnabled; - } - - @Override - public boolean isTimeEnabled() { - return isTimerEnabled; - } - - @Override - public RuntimeException interceptException(Throwable e) { - return null; - } - - @Override - public Collection dumpHandlers() { - return dumpHandlers; - } - - @Override - public Collection verifyHandlers() { - return verifyHandlers; - } - - @Override - public PrintStream output() { - return output; - } - - @Override - public void addToContext(Object o) { - } - - @Override - public void removeFromContext(Object o) { - } - }; - } - - private static final DebugCounter VOID_COUNTER = new DebugCounter() { - - @Override - public void increment() { - } - - @Override - public void add(long value) { - } - - @Override - public void setConditional(boolean flag) { - throw new InternalError("Cannot make void counter conditional"); - } - - @Override - public boolean isConditional() { - return false; - } - - @Override - public long getCurrentValue() { - return 0L; - } - }; - - private static final DebugMethodMetrics VOID_MM = new DebugMethodMetrics() { - - @Override - public void addToMetric(long value, String metricName) { - } - - @Override - public void addToMetric(long value, String format, Object arg1) { - } - - @Override - public void addToMetric(long value, String format, Object arg1, Object arg2) { - } - - @Override - public void addToMetric(long value, String format, Object arg1, Object arg2, Object arg3) { - } - - @Override - public void incrementMetric(String metricName) { - } - - @Override - public void incrementMetric(String format, Object arg1) { - } - - @Override - public void incrementMetric(String format, Object arg1, Object arg2) { - } - - @Override - public void incrementMetric(String format, Object arg1, Object arg2, Object arg3) { - } - - @Override - public long getCurrentMetricValue(String metricName) { - return 0; - } - - @Override - public long getCurrentMetricValue(String format, Object arg1) { - return 0; - } - - @Override - public long getCurrentMetricValue(String format, Object arg1, Object arg2) { - return 0; - } - - @Override - public long getCurrentMetricValue(String format, Object arg1, Object arg2, Object arg3) { - return 0; - } - - @Override - public ResolvedJavaMethod getMethod() { - return null; - } - - }; - - private static final DebugMemUseTracker VOID_MEM_USE_TRACKER = new DebugMemUseTracker() { - - @Override - public DebugCloseable start() { - return DebugCloseable.VOID_CLOSEABLE; - } - - @Override - public long getCurrentValue() { - return 0; - } - }; - - /** - * @see #timer(CharSequence) - */ - public static final String ENABLE_TIMER_PROPERTY_NAME_PREFIX = "graaldebug.timer."; - - /** - * @see #counter(CharSequence) - */ - public static final String ENABLE_COUNTER_PROPERTY_NAME_PREFIX = "graaldebug.counter."; - - /** - * Set of unconditionally enabled counters. Possible values and their meanings: - *
        - *
      • {@code null}: no unconditionally enabled counters
      • - *
      • {@code isEmpty()}: all counters are unconditionally enabled
      • - *
      • {@code !isEmpty()}: use {@link #findMatch(Set, Set, String)} on this set and - * {@link #enabledCountersSubstrings} to determine which counters are unconditionally enabled - *
      • - *
      - */ - private static final Set enabledCounters; - - /** - * Set of unconditionally enabled timers. Same interpretation of values as for - * {@link #enabledCounters}. - */ - private static final Set enabledTimers; - - private static final Set enabledCountersSubstrings = new HashSet<>(); - private static final Set enabledTimersSubstrings = new HashSet<>(); - - /** - * Specifies if all mem use trackers are unconditionally enabled. - */ - private static final boolean isUnconditionalMemUseTrackingEnabled; - - static { - Set counters = new HashSet<>(); - Set timers = new HashSet<>(); - parseCounterAndTimerSystemProperties(counters, timers, enabledCountersSubstrings, enabledTimersSubstrings); - counters = counters.isEmpty() && enabledCountersSubstrings.isEmpty() ? null : counters; - timers = timers.isEmpty() && enabledTimersSubstrings.isEmpty() ? null : timers; - if (counters == null && params.enableUnscopedCounters && !params.enableMethodFilter) { - counters = Collections.emptySet(); - } - if (timers == null && params.enableUnscopedTimers && !params.enableMethodFilter) { - timers = Collections.emptySet(); - } - enabledCounters = counters; - enabledTimers = timers; - isUnconditionalMemUseTrackingEnabled = params.enableUnscopedMemUseTrackers; - DebugValueFactory = initDebugValueFactory(); - } - - private static DebugValueFactory initDebugValueFactory() { - return new DebugValueFactory() { - - @Override - public DebugTimer createTimer(String name, boolean conditional) { - return new TimerImpl(name, conditional, params.interceptTime); - } - - @Override - public DebugCounter createCounter(String name, boolean conditional) { - return CounterImpl.create(name, conditional, params.interceptCount); - } - - @Override - public DebugMethodMetrics createMethodMetrics(ResolvedJavaMethod method) { - return MethodMetricsImpl.getMethodMetrics(method); - } - - @Override - public DebugMemUseTracker createMemUseTracker(String name, boolean conditional) { - return new MemUseTrackerImpl(name, conditional, params.interceptMem); - } - }; - } - - private static DebugValueFactory DebugValueFactory; - - public static void setDebugValueFactory(DebugValueFactory factory) { - Objects.requireNonNull(factory); - DebugValueFactory = factory; - } - - public static DebugValueFactory getDebugValueFactory() { - return DebugValueFactory; - } - - private static boolean findMatch(Set haystack, Set haystackSubstrings, String needle) { - if (haystack.isEmpty() && haystackSubstrings.isEmpty()) { - // Empty haystack means match all - return true; - } - if (haystack.contains(needle)) { - return true; - } - if (!haystackSubstrings.isEmpty()) { - for (String h : haystackSubstrings) { - if (needle.startsWith(h)) { - return true; - } - } - } - return false; - } - - public static boolean areUnconditionalTimersEnabled() { - return enabledTimers != null; - } - - public static boolean areUnconditionalCountersEnabled() { - return enabledCounters != null; - } - - public static boolean isMethodFilteringEnabled() { - return params.enableMethodFilter; - } - - public static boolean areUnconditionalMethodMetricsEnabled() { - // we do not collect mm substrings - return params.enableUnscopedMethodMetrics; - } - - protected static void parseCounterAndTimerSystemProperties(Set counters, Set timers, Set countersSubstrings, Set timersSubstrings) { - do { - try { - for (Map.Entry e : System.getProperties().entrySet()) { - String name = e.getKey().toString(); - if (name.startsWith(ENABLE_COUNTER_PROPERTY_NAME_PREFIX) && Boolean.parseBoolean(e.getValue().toString())) { - if (name.endsWith("*")) { - countersSubstrings.add(name.substring(ENABLE_COUNTER_PROPERTY_NAME_PREFIX.length(), name.length() - 1)); - } else { - counters.add(name.substring(ENABLE_COUNTER_PROPERTY_NAME_PREFIX.length())); - } - } - if (name.startsWith(ENABLE_TIMER_PROPERTY_NAME_PREFIX) && Boolean.parseBoolean(e.getValue().toString())) { - if (name.endsWith("*")) { - timersSubstrings.add(name.substring(ENABLE_TIMER_PROPERTY_NAME_PREFIX.length(), name.length() - 1)); - } else { - timers.add(name.substring(ENABLE_TIMER_PROPERTY_NAME_PREFIX.length())); - } - } - } - return; - } catch (ConcurrentModificationException e) { - // Iterating over the system properties may race with another thread that is - // updating the system properties. Simply try again in this case. - } - } while (true); - } - - /** - * Creates a {@linkplain DebugTimer timer} that is enabled iff debugging is - * {@linkplain #isEnabled() enabled} or the system property whose name is formed by adding - * {@value #ENABLE_TIMER_PROPERTY_NAME_PREFIX} to {@code name} is - * {@linkplain Boolean#getBoolean(String) true}. If the latter condition is true, then the - * returned timer is {@linkplain DebugCounter#isConditional() unconditional} otherwise it is - * conditional. - *

      - * A disabled timer has virtually no overhead. - */ - public static DebugTimer timer(CharSequence name) { - if (!areUnconditionalTimersEnabled() && !ENABLED) { - return VOID_TIMER; - } - return createTimer("%s", name, null); - } - - /** - * Creates a debug timer. Invoking this method is equivalent to: - * - *

      -     * Debug.timer(format, arg, null)
      -     * 
      - * - * except that the string formatting only happens if timing is enabled. - * - * @see #timer(String, Object, Object) - */ - public static DebugTimer timer(String format, Object arg) { - if (!areUnconditionalTimersEnabled() && !ENABLED) { - return VOID_TIMER; - } - return createTimer(format, arg, null); - } - - /** - * Creates a debug timer. Invoking this method is equivalent to: - * - *
      -     * Debug.timer(String.format(format, arg1, arg2))
      -     * 
      - * - * except that the string formatting only happens if timing is enabled. In addition, each - * argument is subject to the following type based conversion before being passed as an argument - * to {@link String#format(String, Object...)}: - * - *
      -     *     Type          | Conversion
      -     * ------------------+-----------------
      -     *  java.lang.Class  | arg.getSimpleName()
      -     *                   |
      -     * 
      - * - * @see #timer(CharSequence) - */ - public static DebugTimer timer(String format, Object arg1, Object arg2) { - if (!areUnconditionalTimersEnabled() && !ENABLED) { - return VOID_TIMER; - } - return createTimer(format, arg1, arg2); - } - - /** - * There are paths where construction of formatted class names are common and the code below is - * surprisingly expensive, so compute it once and cache it. - */ - private static final ClassValue formattedClassName = new ClassValue() { - @Override - protected String computeValue(Class c) { - final String simpleName = c.getSimpleName(); - Class enclosingClass = c.getEnclosingClass(); - if (enclosingClass != null) { - String prefix = ""; - while (enclosingClass != null) { - prefix = enclosingClass.getSimpleName() + "_" + prefix; - enclosingClass = enclosingClass.getEnclosingClass(); - } - return prefix + simpleName; - } else { - return simpleName; - } - } - }; - - public static Object convertFormatArg(Object arg) { - if (arg instanceof Class) { - return formattedClassName.get((Class) arg); - } - return arg; - } - - private static String formatDebugName(String format, Object arg1, Object arg2) { - return String.format(format, convertFormatArg(arg1), convertFormatArg(arg2)); - } - - private static DebugTimer createTimer(String format, Object arg1, Object arg2) { - String name = formatDebugName(format, arg1, arg2); - boolean conditional = enabledTimers == null || !findMatch(enabledTimers, enabledTimersSubstrings, name); - if (!ENABLED && conditional) { - return VOID_TIMER; - } - return DebugValueFactory.createTimer(name, conditional); - } - - private static final DebugTimer VOID_TIMER = new DebugTimer() { - - @Override - public DebugCloseable start() { - return DebugCloseable.VOID_CLOSEABLE; - } - - @Override - public void setConditional(boolean flag) { - throw new InternalError("Cannot make void timer conditional"); - } - - @Override - public boolean isConditional() { - return false; - } - - @Override - public long getCurrentValue() { - return 0L; - } - - @Override - public TimeUnit getTimeUnit() { - return null; - } - }; -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugCloseable.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugCloseable.java index 50aad685d60..6d5a2cbed7e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugCloseable.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugCloseable.java @@ -34,6 +34,13 @@ public interface DebugCloseable extends AutoCloseable { } }; + /** + * Gets the debug context associated with this object. + */ + default DebugContext getDebug() { + return null; + } + @Override void close(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfig.java index 66b5c32311f..75ff4981e7a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfig.java @@ -25,79 +25,68 @@ package org.graalvm.compiler.debug; import java.io.PrintStream; import java.util.Collection; +import org.graalvm.compiler.debug.DebugContext.Scope; +import org.graalvm.compiler.options.OptionValues; + +import jdk.vm.ci.meta.JavaMethod; + public interface DebugConfig { /** - * Determines the current log level in the {@linkplain Debug#currentScope() current debug scope} - * . + * Returns the option values used to configure this object. */ - int getLogLevel(); + OptionValues getOptions(); /** - * Determines the current dump level in the {@linkplain Debug#currentScope() current debug - * scope}. + * Determines the current log level in {@code scope}. */ - int getDumpLevel(); + int getLogLevel(DebugContext.Scope scope); /** - * Determines if logging can be enabled in the current method, regardless of the - * {@linkplain Debug#currentScope() current debug scope}. + * Determines the current dump level in {@code scope}. */ - boolean isLogEnabledForMethod(); + int getDumpLevel(DebugContext.Scope scope); /** - * Determines if counting is enabled in the {@linkplain Debug#currentScope() current debug - * scope}. + * Determines if logging is enabled for any {@link JavaMethod} in {@code scope}'s + * {@linkplain Scope#getCurrentContext() context}. + */ + boolean isLogEnabledForMethod(DebugContext.Scope scope); + + /** + * Determines if counting is enabled in {@code scope}. * - * @see Debug#counter(CharSequence) + * @see DebugContext#counter(CharSequence) */ - boolean isCountEnabled(); + boolean isCountEnabled(DebugContext.Scope scope); /** - * Determines if memory use tracking is enabled in the {@linkplain Debug#currentScope() current - * debug scope}. + * Determines if memory use tracking is {@code scope}. * - * @see Debug#memUseTracker(CharSequence) + * @see DebugContext#memUseTracker(CharSequence) */ - boolean isMemUseTrackingEnabled(); + boolean isMemUseTrackingEnabled(DebugContext.Scope scope); /** - * Determines if dumping can be enabled in the current method, regardless of the - * {@linkplain Debug#currentScope() current debug scope}. + * Determines if dumping is enabled for any {@link JavaMethod} in {@code scope}'s + * {@linkplain Scope#getCurrentContext() context}. */ - boolean isDumpEnabledForMethod(); + boolean isDumpEnabledForMethod(DebugContext.Scope scope); /** - * @see Debug#isVerifyEnabled() + * @see DebugContext#isVerifyEnabled() */ - boolean isVerifyEnabled(); + boolean isVerifyEnabled(DebugContext.Scope scope); /** - * @see Debug#isVerifyEnabledForMethod() + * @see DebugContext#isVerifyEnabledForMethod() */ - boolean isVerifyEnabledForMethod(); + boolean isVerifyEnabledForMethod(DebugContext.Scope scope); /** - * @see Debug#isMethodMeterEnabled() + * @see DebugContext#timer(CharSequence) */ - boolean isMethodMeterEnabled(); - - /** - * Adds an object the context used by this configuration to do filtering. - */ - void addToContext(Object o); - - /** - * Removes an object the context used by this configuration to do filtering. - * - * This should only removes extra context added by {@link #addToContext(Object)}. - */ - void removeFromContext(Object o); - - /** - * @see Debug#timer(CharSequence) - */ - boolean isTimeEnabled(); + boolean isTimeEnabled(DebugContext.Scope scope); /** * Handles notification of an exception occurring within a debug scope. @@ -105,18 +94,47 @@ public interface DebugConfig { * @return the exception object that is to be propagated to parent scope. A value of * {@code null} indicates that {@code e} is to be propagated. */ - RuntimeException interceptException(Throwable e); + RuntimeException interceptException(DebugContext debug, Throwable e); /** - * Gets the modifiable collection of dump handlers registered with this configuration. + * Gets an unmodifiable view of the dump handlers registered with this configuration. */ Collection dumpHandlers(); + /** + * Gets the {@link PrintStream} for logging. + */ PrintStream output(); /** - * Gets the modifiable collection of verify handlers registered with this configuration. + * Gets an unmodifiable view of the verify handlers registered with this configuration. */ Collection verifyHandlers(); + default void closeDumpHandlers(boolean ignoreErrors) { + for (DebugDumpHandler handler : dumpHandlers()) { + try { + handler.close(); + } catch (Throwable e) { + if (!ignoreErrors) { + throw e; + } + } + } + } + + /** + * Extracts a {@link JavaMethod} from an opaque debug context. + * + * @return the {@link JavaMethod} represented by {@code context} or null + */ + static JavaMethod asJavaMethod(Object context) { + if (context instanceof JavaMethodContext) { + return ((JavaMethodContext) context).asJavaMethod(); + } + if (context instanceof JavaMethod) { + return (JavaMethod) context; + } + return null; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigImpl.java new file mode 100644 index 00000000000..65a9833624d --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigImpl.java @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import static org.graalvm.compiler.debug.DebugContext.BASIC_LEVEL; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; + +import org.graalvm.compiler.options.OptionValues; + +import jdk.vm.ci.code.BailoutException; +import jdk.vm.ci.meta.JavaMethod; + +final class DebugConfigImpl implements DebugConfig { + + private final OptionValues options; + + private final DebugFilter countFilter; + private final DebugFilter logFilter; + private final DebugFilter trackMemUseFilter; + private final DebugFilter timerFilter; + private final DebugFilter dumpFilter; + private final DebugFilter verifyFilter; + private final MethodFilter[] methodFilter; + private final List dumpHandlers; + private final List verifyHandlers; + private final PrintStream output; + + DebugConfigImpl(OptionValues options) { + this(options, TTY.out, Collections.emptyList(), Collections.emptyList()); + } + + DebugConfigImpl(OptionValues options, PrintStream output, + List dumpHandlers, + List verifyHandlers) { + this(options, DebugOptions.Log.getValue(options), + DebugOptions.Count.getValue(options), + DebugOptions.TrackMemUse.getValue(options), + DebugOptions.Time.getValue(options), + DebugOptions.Dump.getValue(options), + getVerifyOptionValue(options), + DebugOptions.MethodFilter.getValue(options), + output, dumpHandlers, verifyHandlers); + } + + DebugConfigImpl(OptionValues options, + String logFilter, + String countFilter, + String trackMemUseFilter, + String timerFilter, + String dumpFilter, + String verifyFilter, + String methodFilter, + PrintStream output, + List dumpHandlers, + List verifyHandlers) { + this.options = options; + this.logFilter = DebugFilter.parse(logFilter); + this.countFilter = DebugFilter.parse(countFilter); + this.trackMemUseFilter = DebugFilter.parse(trackMemUseFilter); + this.timerFilter = DebugFilter.parse(timerFilter); + this.dumpFilter = DebugFilter.parse(dumpFilter); + this.verifyFilter = DebugFilter.parse(verifyFilter); + if (methodFilter == null || methodFilter.isEmpty()) { + this.methodFilter = null; + } else { + this.methodFilter = org.graalvm.compiler.debug.MethodFilter.parse(methodFilter); + } + + this.dumpHandlers = Collections.unmodifiableList(dumpHandlers); + this.verifyHandlers = Collections.unmodifiableList(verifyHandlers); + this.output = output; + } + + private static String getVerifyOptionValue(OptionValues values) { + return !DebugOptions.Verify.hasBeenSet(values) && Assertions.assertionsEnabled() ? "" : DebugOptions.Verify.getValue(values); + } + + @Override + public OptionValues getOptions() { + return options; + } + + @Override + public int getLogLevel(DebugContext.Scope scope) { + return getLevel(scope, logFilter); + } + + @Override + public boolean isLogEnabledForMethod(DebugContext.Scope scope) { + return isEnabledForMethod(scope, logFilter); + } + + @Override + public boolean isCountEnabled(DebugContext.Scope scope) { + return isEnabled(scope, countFilter); + } + + @Override + public boolean isMemUseTrackingEnabled(DebugContext.Scope scope) { + return isEnabled(scope, trackMemUseFilter); + } + + @Override + public int getDumpLevel(DebugContext.Scope scope) { + return getLevel(scope, dumpFilter); + } + + @Override + public boolean isDumpEnabledForMethod(DebugContext.Scope scope) { + return isEnabledForMethod(scope, dumpFilter); + } + + @Override + public boolean isVerifyEnabled(DebugContext.Scope scope) { + return isEnabled(scope, verifyFilter); + } + + @Override + public boolean isVerifyEnabledForMethod(DebugContext.Scope scope) { + return isEnabledForMethod(scope, verifyFilter); + } + + @Override + public boolean isTimeEnabled(DebugContext.Scope scope) { + return isEnabled(scope, timerFilter); + } + + @Override + public PrintStream output() { + return output; + } + + private boolean isEnabled(DebugContext.Scope scope, DebugFilter filter) { + return getLevel(scope, filter) > 0; + } + + private int getLevel(DebugContext.Scope scope, DebugFilter filter) { + int level; + if (filter == null) { + level = 0; + } else { + String currentScope = scope.getQualifiedName(); + level = filter.matchLevel(currentScope); + } + if (level >= 0 && !checkMethodFilter(scope)) { + level = -1; + } + return level; + } + + private boolean isEnabledForMethod(DebugContext.Scope scope, DebugFilter filter) { + return filter != null && checkMethodFilter(scope); + } + + private boolean checkMethodFilter(DebugContext.Scope scope) { + if (methodFilter == null) { + return true; + } else { + JavaMethod lastMethod = null; + Iterable context = scope.getCurrentContext(); + for (Object o : context) { + if (methodFilter != null) { + JavaMethod method = DebugConfig.asJavaMethod(o); + if (method != null) { + if (!DebugOptions.MethodFilterRootOnly.getValue(options)) { + if (org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, method)) { + return true; + } + } else { + /* + * The context values operate as a stack so if we want MethodFilter to + * only apply to the root method we have to check only the last method + * seen. + */ + lastMethod = method; + } + } + } + } + if (lastMethod != null && org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, lastMethod)) { + return true; + } + return false; + } + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Debug config:"); + add(sb, "Log", logFilter); + add(sb, "Count", countFilter); + add(sb, "Time", timerFilter); + add(sb, "Dump", dumpFilter); + add(sb, "MethodFilter", methodFilter); + return sb.toString(); + } + + private static void add(StringBuilder sb, String name, Object filter) { + if (filter != null) { + sb.append(' '); + sb.append(name); + sb.append('='); + if (filter instanceof Object[]) { + sb.append(Arrays.toString((Object[]) filter)); + } else { + sb.append(String.valueOf(filter)); + } + } + } + + @Override + public RuntimeException interceptException(DebugContext debug, Throwable e) { + if (e instanceof BailoutException && !DebugOptions.InterceptBailout.getValue(options)) { + return null; + } + + OptionValues interceptOptions = new OptionValues(options, + DebugOptions.Count, null, + DebugOptions.Time, null, + DebugOptions.TrackMemUse, null, + DebugOptions.Verify, null, + DebugOptions.Dump, ":" + BASIC_LEVEL, + DebugOptions.Log, ":" + BASIC_LEVEL); + DebugConfigImpl config = new DebugConfigImpl(interceptOptions, output, dumpHandlers, verifyHandlers); + ScopeImpl scope = debug.currentScope; + scope.updateFlags(config); + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + e.printStackTrace(new PrintStream(baos)); + debug.log("Exception raised in scope %s: %s", debug.getCurrentScopeName(), baos); + Map firstSeen = new IdentityHashMap<>(); + for (Object o : debug.context()) { + // Only dump a context object once. + if (!firstSeen.containsKey(o)) { + firstSeen.put(o, o); + if (DebugOptions.DumpOnError.getValue(options) || DebugOptions.Dump.getValue(options) != null) { + debug.dump(DebugContext.BASIC_LEVEL, o, "Exception: %s", e); + } else { + debug.log("Context obj %s", o); + } + } + } + } finally { + scope.updateFlags(this); + } + return null; + } + + @Override + public Collection dumpHandlers() { + return dumpHandlers; + } + + @Override + public Collection verifyHandlers() { + return verifyHandlers; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java new file mode 100644 index 00000000000..d79064c9c3b --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java @@ -0,0 +1,2033 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import static java.util.FormattableFlags.LEFT_JUSTIFY; +import static java.util.FormattableFlags.UPPERCASE; +import static org.graalvm.compiler.debug.DebugOptions.Count; +import static org.graalvm.compiler.debug.DebugOptions.Counters; +import static org.graalvm.compiler.debug.DebugOptions.Dump; +import static org.graalvm.compiler.debug.DebugOptions.DumpOnError; +import static org.graalvm.compiler.debug.DebugOptions.DumpOnPhaseChange; +import static org.graalvm.compiler.debug.DebugOptions.ListMetrics; +import static org.graalvm.compiler.debug.DebugOptions.Log; +import static org.graalvm.compiler.debug.DebugOptions.MemUseTrackers; +import static org.graalvm.compiler.debug.DebugOptions.Time; +import static org.graalvm.compiler.debug.DebugOptions.Timers; +import static org.graalvm.compiler.debug.DebugOptions.TrackMemUse; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Formatter; +import java.util.List; +import java.util.Map; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.EconomicSet; +import org.graalvm.util.Pair; + +import jdk.vm.ci.meta.JavaMethod; + +/** + * A facility for logging and dumping as well as a container for values associated with + * {@link MetricKey}s. + * + * A {@code DebugContext} object must only be used on the thread that created it. This means it + * needs to be passed around as a parameter. For convenience, it can be encapsulated in a widely + * used object that is in scope wherever a {@code DebugContext} is needed. However, care must be + * taken when such objects can be exposed to multiple threads (e.g., they are in a non-thread-local + * cache). + */ +public final class DebugContext implements AutoCloseable { + + public static final Description NO_DESCRIPTION = null; + public static final GlobalMetrics NO_GLOBAL_METRIC_VALUES = null; + public static final Iterable NO_CONFIG_CUSTOMIZERS = Collections.emptyList(); + + public static final PrintStream DEFAULT_LOG_STREAM = TTY.out; + + /** + * Contains the immutable parts of a debug context. This separation allows the immutable parts + * to be shared and reduces the overhead of initialization since most immutable fields are + * configured by parsing options. + */ + final Immutable immutable; + + /** + * Determines whether metrics are enabled. + */ + boolean metricsEnabled; + + DebugConfig currentConfig; + ScopeImpl currentScope; + CloseableCounter currentTimer; + CloseableCounter currentMemUseTracker; + Scope lastClosedScope; + Throwable lastExceptionThrown; + + /** + * Stores the {@link MetricKey} values. + */ + private long[] metricValues; + + /** + * Determines if dynamic scopes are enabled. + */ + public boolean areScopesEnabled() { + return immutable.scopesEnabled; + } + + /** + * The immutable configuration that can be shared between {@link DebugContext} objects. + */ + static final class Immutable { + + private static final Immutable[] CACHE = new Immutable[5]; + + /** + * The options from which this object was configured. + */ + final OptionValues options; + + /** + * Specifies if dynamic scopes are enabled. + */ + final boolean scopesEnabled; + + final boolean listMetrics; + + /** + * Names of unscoped counters. A counter is unscoped if this set is empty or contains the + * counter's name. + */ + final EconomicSet unscopedCounters; + + /** + * Names of unscoped timers. A timer is unscoped if this set is empty or contains the + * timer's name. + */ + final EconomicSet unscopedTimers; + + /** + * Names of unscoped memory usage trackers. A memory usage tracker is unscoped if this set + * is empty or contains the memory usage tracker's name. + */ + final EconomicSet unscopedMemUseTrackers; + + private static EconomicSet parseUnscopedMetricSpec(String spec, boolean unconditional, boolean accumulatedKey) { + EconomicSet res; + if (spec == null) { + if (!unconditional) { + res = null; + } else { + res = EconomicSet.create(); + } + } else { + res = EconomicSet.create(); + if (!spec.isEmpty()) { + if (!accumulatedKey) { + res.addAll(Arrays.asList(spec.split(","))); + } else { + for (String n : spec.split(",")) { + res.add(n + AccumulatedKey.ACCUMULATED_KEY_SUFFIX); + res.add(n + AccumulatedKey.FLAT_KEY_SUFFIX); + } + } + + } + } + return res; + } + + static Immutable create(OptionValues options) { + int i = 0; + while (i < CACHE.length) { + Immutable immutable = CACHE[i]; + if (immutable == null) { + break; + } + if (immutable.options == options) { + return immutable; + } + i++; + } + Immutable immutable = new Immutable(options); + if (i < CACHE.length) { + CACHE[i] = immutable; + } + return immutable; + } + + private static boolean isNotEmpty(OptionKey option, OptionValues options) { + return option.getValue(options) != null && !option.getValue(options).isEmpty(); + } + + private Immutable(OptionValues options) { + this.options = options; + this.unscopedCounters = parseUnscopedMetricSpec(Counters.getValue(options), "".equals(Count.getValue(options)), false); + this.unscopedTimers = parseUnscopedMetricSpec(Timers.getValue(options), "".equals(Time.getValue(options)), true); + this.unscopedMemUseTrackers = parseUnscopedMetricSpec(MemUseTrackers.getValue(options), "".equals(TrackMemUse.getValue(options)), true); + + this.scopesEnabled = DumpOnError.getValue(options) || + Dump.getValue(options) != null || + Log.getValue(options) != null || + isNotEmpty(DebugOptions.Count, options) || + isNotEmpty(DebugOptions.Time, options) || + isNotEmpty(DebugOptions.TrackMemUse, options) || + DumpOnPhaseChange.getValue(options) != null; + this.listMetrics = ListMetrics.getValue(options); + } + + private Immutable() { + this.options = new OptionValues(EconomicMap.create()); + this.unscopedCounters = null; + this.unscopedTimers = null; + this.unscopedMemUseTrackers = null; + this.scopesEnabled = false; + this.listMetrics = false; + } + + public boolean hasUnscopedMetrics() { + return unscopedCounters != null || unscopedTimers != null || unscopedMemUseTrackers != null; + } + } + + /** + * Gets the options this debug context was constructed with. + */ + public OptionValues getOptions() { + return immutable.options; + } + + static class Activated extends ThreadLocal { + } + + private static final Activated activated = new Activated(); + + /** + * An object used to undo the changes made by DebugContext#activate(). + */ + public static class Activation implements AutoCloseable { + private final DebugContext parent; + + Activation(DebugContext parent) { + this.parent = parent; + } + + @Override + public void close() { + activated.set(parent); + } + } + + /** + * Activates this object as the debug context {@linkplain DebugContext#forCurrentThread for the + * current thread}. This method should be used in a try-with-resources statement. + * + * @return an object that will deactivate the debug context for the current thread when + * {@link Activation#close()} is called on it + */ + public Activation activate() { + Activation res = new Activation(activated.get()); + activated.set(this); + return res; + } + + /** + * Shared object used to represent a disabled debug context. + */ + public static final DebugContext DISABLED = new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, new Immutable(), NO_CONFIG_CUSTOMIZERS); + + /** + * Gets the debug context for the current thread. This should only be used when there is no + * other reasonable means to get a hold of a debug context. + */ + public static DebugContext forCurrentThread() { + DebugContext current = activated.get(); + if (current == null) { + return DISABLED; + } + return current; + } + + private final GlobalMetrics globalMetrics; + + /** + * Describes the computation associated with a {@link DebugContext}. + */ + public static class Description { + /** + * The primary input to the computation. + */ + final Object compilable; + + /** + * A runtime based identifier that is most likely to be unique. + */ + final String identifier; + + public Description(Object compilable, String identifier) { + this.compilable = compilable; + this.identifier = identifier; + } + + @Override + public String toString() { + String compilableName = compilable instanceof JavaMethod ? ((JavaMethod) compilable).format("%H.%n(%p)%R") : String.valueOf(compilable); + return identifier + ":" + compilableName; + } + } + + private final Description description; + + /** + * Gets a description of the computation associated with this debug context. + * + * @return {@code null} if no description is available + */ + public Description getDescription() { + return description; + } + + /** + * Gets the global metrics associated with this debug context. + * + * @return {@code null} if no global metrics are available + */ + public GlobalMetrics getGlobalMetrics() { + return globalMetrics; + } + + /** + * Creates a {@link DebugContext} based on a given set of option values and {@code factory}. + */ + public static DebugContext create(OptionValues options, DebugHandlersFactory factory) { + return new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, Immutable.create(options), Collections.singletonList(factory)); + } + + /** + * Creates a {@link DebugContext} based on a given set of option values and {@code factories}. + * The {@link DebugHandlersFactory#LOADER} can be used for the latter. + */ + public static DebugContext create(OptionValues options, Iterable factories) { + return new DebugContext(NO_DESCRIPTION, NO_GLOBAL_METRIC_VALUES, DEFAULT_LOG_STREAM, Immutable.create(options), factories); + } + + /** + * Creates a {@link DebugContext}. + */ + public static DebugContext create(OptionValues options, Description description, GlobalMetrics globalMetrics, PrintStream logStream, Iterable factories) { + return new DebugContext(description, globalMetrics, logStream, Immutable.create(options), factories); + } + + private DebugContext(Description description, GlobalMetrics globalMetrics, PrintStream logStream, Immutable immutable, Iterable factories) { + this.immutable = immutable; + this.description = description; + this.globalMetrics = globalMetrics; + if (immutable.scopesEnabled) { + OptionValues options = immutable.options; + List dumpHandlers = new ArrayList<>(); + List verifyHandlers = new ArrayList<>(); + for (DebugHandlersFactory factory : factories) { + for (DebugHandler handler : factory.createHandlers(options)) { + if (handler instanceof DebugDumpHandler) { + dumpHandlers.add((DebugDumpHandler) handler); + } else { + assert handler instanceof DebugVerifyHandler; + verifyHandlers.add((DebugVerifyHandler) handler); + } + } + } + currentConfig = new DebugConfigImpl(options, logStream, dumpHandlers, verifyHandlers); + currentScope = new ScopeImpl(this, Thread.currentThread()); + currentScope.updateFlags(currentConfig); + metricsEnabled = true; + } else { + metricsEnabled = immutable.hasUnscopedMetrics() || immutable.listMetrics; + } + } + + /** + * A special dump level that indicates the dumping machinery is enabled but no dumps will be + * produced except through other options. + */ + public static final int ENABLED_LEVEL = 0; + + /** + * Basic debug level. + * + * For HIR dumping, only ~5 graphs per method: after parsing, after inlining, after high tier, + * after mid tier, after low tier. + * + * LIR dumping: After LIR generation, after each pre-allocation, allocation and post allocation + * stage, and after code installation. + */ + public static final int BASIC_LEVEL = 1; + + /** + * Informational debug level. + * + * HIR dumping: One graph after each applied top-level phase. + * + * LIR dumping: After each applied phase. + */ + public static final int INFO_LEVEL = 2; + + /** + * Verbose debug level. + * + * HIR dumping: One graph after each phase (including sub phases). + * + * LIR dumping: After each phase including sub phases. + */ + public static final int VERBOSE_LEVEL = 3; + + /** + * Detailed debug level. + * + * HIR dumping: Graphs within phases where interesting for a phase, max ~5 per phase. + * + * LIR dumping: Dump CFG within phases where interesting. + */ + public static final int DETAILED_LEVEL = 4; + + /** + * Very detailed debug level. + * + * HIR dumping: Graphs per node granularity graph change (before/after change). + * + * LIR dumping: Intermediate CFGs of phases where interesting. + */ + public static final int VERY_DETAILED_LEVEL = 5; + + public boolean isDumpEnabled(int dumpLevel) { + return currentScope != null && currentScope.isDumpEnabled(dumpLevel); + } + + /** + * Determines if verification is enabled for any {@link JavaMethod} in the current scope. + * + * @see DebugContext#verify(Object, String) + */ + public boolean isVerifyEnabledForMethod() { + if (currentScope == null) { + return false; + } + if (currentConfig == null) { + return false; + } + return currentConfig.isVerifyEnabledForMethod(currentScope); + } + + /** + * Determines if verification is enabled in the current scope. + * + * @see DebugContext#verify(Object, String) + */ + public boolean isVerifyEnabled() { + return currentScope != null && currentScope.isVerifyEnabled(); + } + + public boolean isCountEnabled() { + return currentScope != null && currentScope.isCountEnabled(); + } + + public boolean isTimeEnabled() { + return currentScope != null && currentScope.isTimeEnabled(); + } + + public boolean isMemUseTrackingEnabled() { + return currentScope != null && currentScope.isMemUseTrackingEnabled(); + } + + public boolean isDumpEnabledForMethod() { + if (currentConfig == null) { + return false; + } + return currentConfig.isDumpEnabledForMethod(currentScope); + } + + public boolean isLogEnabledForMethod() { + if (currentScope == null) { + return false; + } + if (currentConfig == null) { + return false; + } + return currentConfig.isLogEnabledForMethod(currentScope); + } + + public boolean isLogEnabled() { + return currentScope != null && isLogEnabled(BASIC_LEVEL); + } + + public boolean isLogEnabled(int logLevel) { + return currentScope != null && currentScope.isLogEnabled(logLevel); + } + + /** + * Gets a string composed of the names in the current nesting of debug + * {@linkplain #scope(Object) scopes} separated by {@code '.'}. + */ + public String getCurrentScopeName() { + if (currentScope != null) { + return currentScope.getQualifiedName(); + } else { + return ""; + } + } + + /** + * Creates and enters a new debug scope which will be a child of the current debug scope. + *

      + * It is recommended to use the try-with-resource statement for managing entering and leaving + * debug scopes. For example: + * + *

      +     * try (Scope s = Debug.scope("InliningGraph", inlineeGraph)) {
      +     *     ...
      +     * } catch (Throwable e) {
      +     *     throw Debug.handle(e);
      +     * }
      +     * 
      + * + * The {@code name} argument is subject to the following type based conversion before having + * {@link Object#toString()} called on it: + * + *
      +     *     Type          | Conversion
      +     * ------------------+-----------------
      +     *  java.lang.Class  | arg.getSimpleName()
      +     *                   |
      +     * 
      + * + * @param name the name of the new scope + * @param contextObjects an array of object to be appended to the {@linkplain #context() + * current} debug context + * @throws Throwable used to enforce a catch block. + * @return the scope entered by this method which will be exited when its {@link Scope#close()} + * method is called + */ + public DebugContext.Scope scope(Object name, Object[] contextObjects) throws Throwable { + if (currentScope != null) { + return enterScope(convertFormatArg(name).toString(), null, contextObjects); + } else { + return null; + } + } + + /** + * Similar to {@link #scope(Object, Object[])} but without context objects. Therefore the catch + * block can be omitted. + * + * @see #scope(Object, Object[]) + */ + public DebugContext.Scope scope(Object name) { + if (currentScope != null) { + return enterScope(convertFormatArg(name).toString(), null); + } else { + return null; + } + } + + private final Invariants invariants = Assertions.assertionsEnabled() ? new Invariants() : null; + + static StackTraceElement[] getStackTrace(Thread thread) { + return thread.getStackTrace(); + } + + /** + * Utility for enforcing {@link DebugContext} invariants via assertions. + */ + static class Invariants { + private final Thread thread; + private final StackTraceElement[] origin; + + Invariants() { + thread = Thread.currentThread(); + origin = getStackTrace(thread); + } + + boolean checkNoConcurrentAccess() { + Thread currentThread = Thread.currentThread(); + if (currentThread != thread) { + Formatter buf = new Formatter(); + buf.format("Thread local %s object was created on thread %s but is being accessed by thread %s. The most likely cause is " + + "that the object is being retrieved from a non-thread-local cache.", + DebugContext.class.getName(), thread, currentThread); + int debugContextConstructors = 0; + boolean addedHeader = false; + for (StackTraceElement e : origin) { + if (e.getMethodName().equals("") && e.getClassName().equals(DebugContext.class.getName())) { + debugContextConstructors++; + } else if (debugContextConstructors != 0) { + if (!addedHeader) { + addedHeader = true; + buf.format(" The object was instantiated here:"); + } + // Distinguish from assertion stack trace by using double indent and + // "in" instead of "at" prefix. + buf.format("%n\t\tin %s", e); + } + } + if (addedHeader) { + buf.format("%n"); + } + + throw new AssertionError(buf.toString()); + } + return true; + } + } + + boolean checkNoConcurrentAccess() { + assert invariants == null || invariants.checkNoConcurrentAccess(); + return true; + } + + private DebugContext.Scope enterScope(CharSequence name, DebugConfig sandboxConfig, Object... newContextObjects) { + assert checkNoConcurrentAccess(); + currentScope = currentScope.scope(name, sandboxConfig, newContextObjects); + return currentScope; + } + + /** + * @see #scope(Object, Object[]) + * @param context an object to be appended to the {@linkplain #context() current} debug context + */ + public DebugContext.Scope scope(Object name, Object context) throws Throwable { + if (currentScope != null) { + return enterScope(convertFormatArg(name).toString(), null, context); + } else { + return null; + } + } + + /** + * @see #scope(Object, Object[]) + * @param context1 first object to be appended to the {@linkplain #context() current} debug + * context + * @param context2 second object to be appended to the {@linkplain #context() current} debug + * context + */ + public DebugContext.Scope scope(Object name, Object context1, Object context2) throws Throwable { + if (currentScope != null) { + return enterScope(convertFormatArg(name).toString(), null, context1, context2); + } else { + return null; + } + } + + /** + * @see #scope(Object, Object[]) + * @param context1 first object to be appended to the {@linkplain #context() current} debug + * context + * @param context2 second object to be appended to the {@linkplain #context() current} debug + * context + * @param context3 third object to be appended to the {@linkplain #context() current} debug + * context + */ + public DebugContext.Scope scope(Object name, Object context1, Object context2, Object context3) throws Throwable { + if (currentScope != null) { + return enterScope(convertFormatArg(name).toString(), null, context1, context2, context3); + } else { + return null; + } + } + + /** + * Creates and enters a new debug scope which will be disjoint from the current debug scope. + *

      + * It is recommended to use the try-with-resource statement for managing entering and leaving + * debug scopes. For example: + * + *

      +     * try (Scope s = Debug.sandbox("CompilingStub", null, stubGraph)) {
      +     *     ...
      +     * } catch (Throwable e) {
      +     *     throw Debug.handle(e);
      +     * }
      +     * 
      + * + * @param name the name of the new scope + * @param config the debug configuration to use for the new scope or {@code null} to disable the + * scoping mechanism within the sandbox scope + * @param context objects to be appended to the {@linkplain #context() current} debug context + * @return the scope entered by this method which will be exited when its {@link Scope#close()} + * method is called + */ + public DebugContext.Scope sandbox(CharSequence name, DebugConfig config, Object... context) throws Throwable { + if (config == null) { + return disable(); + } + if (currentScope != null) { + return enterScope(name, config, context); + } else { + return null; + } + } + + /** + * Determines if scopes are enabled and this context is in a non-top-level scope. + */ + public boolean inNestedScope() { + if (immutable.scopesEnabled) { + if (currentScope == null) { + // In an active DisabledScope + return true; + } + return !currentScope.isTopLevel(); + } + return immutable.scopesEnabled && currentScope == null; + } + + class DisabledScope implements DebugContext.Scope { + final boolean savedMetricsEnabled; + final ScopeImpl savedScope; + final DebugConfig savedConfig; + + DisabledScope() { + this.savedMetricsEnabled = metricsEnabled; + this.savedScope = currentScope; + this.savedConfig = currentConfig; + metricsEnabled = false; + currentScope = null; + currentConfig = null; + } + + @Override + public String getQualifiedName() { + return ""; + } + + @Override + public Iterable getCurrentContext() { + return Collections.emptyList(); + } + + @Override + public void close() { + metricsEnabled = savedMetricsEnabled; + currentScope = savedScope; + currentConfig = savedConfig; + lastClosedScope = this; + } + } + + /** + * Disables all metrics and scope related functionality until {@code close()} is called on the + * returned object. + */ + public DebugContext.Scope disable() { + if (currentScope != null) { + return new DisabledScope(); + } else { + return null; + } + } + + public DebugContext.Scope forceLog() throws Throwable { + if (currentConfig != null) { + ArrayList context = new ArrayList<>(); + for (Object obj : context()) { + context.add(obj); + } + DebugConfigImpl config = new DebugConfigImpl(new OptionValues(currentConfig.getOptions(), DebugOptions.Log, ":1000")); + return sandbox("forceLog", config, context.toArray()); + } + return null; + } + + /** + * Opens a scope in which exception + * {@linkplain DebugConfig#interceptException(DebugContext, Throwable) interception} is + * disabled. The current state of interception is restored when {@link DebugCloseable#close()} + * is called on the returned object. + * + * This is particularly useful to suppress extraneous output in JUnit tests that are expected to + * throw an exception. + */ + public DebugCloseable disableIntercept() { + if (currentScope != null) { + return currentScope.disableIntercept(); + } + return null; + } + + /** + * Handles an exception in the context of the debug scope just exited. The just exited scope + * must have the current scope as its parent which will be the case if the try-with-resource + * pattern recommended by {@link #scope(Object)} and + * {@link #sandbox(CharSequence, DebugConfig, Object...)} is used + * + * @see #scope(Object, Object[]) + * @see #sandbox(CharSequence, DebugConfig, Object...) + */ + public RuntimeException handle(Throwable exception) { + if (currentScope != null) { + return currentScope.handle(exception); + } else { + if (exception instanceof Error) { + throw (Error) exception; + } + if (exception instanceof RuntimeException) { + throw (RuntimeException) exception; + } + throw new RuntimeException(exception); + } + } + + public void log(String msg) { + log(BASIC_LEVEL, msg); + } + + /** + * Prints a message to the current debug scope's logging stream if logging is enabled. + * + * @param msg the message to log + */ + public void log(int logLevel, String msg) { + if (currentScope != null) { + currentScope.log(logLevel, msg); + } + } + + public void log(String format, Object arg) { + log(BASIC_LEVEL, format, arg); + } + + /** + * Prints a message to the current debug scope's logging stream if logging is enabled. + * + * @param format a format string + * @param arg the argument referenced by the format specifiers in {@code format} + */ + public void log(int logLevel, String format, Object arg) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg); + } + } + + public void log(String format, int arg) { + log(BASIC_LEVEL, format, arg); + } + + /** + * Prints a message to the current debug scope's logging stream if logging is enabled. + * + * @param format a format string + * @param arg the argument referenced by the format specifiers in {@code format} + */ + public void log(int logLevel, String format, int arg) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg); + } + } + + public void log(String format, Object arg1, Object arg2) { + log(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, Object arg1, Object arg2) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2); + } + } + + public void log(String format, int arg1, Object arg2) { + log(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, int arg1, Object arg2) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2); + } + } + + public void log(String format, Object arg1, int arg2) { + log(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, Object arg1, int arg2) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2); + } + } + + public void log(String format, int arg1, int arg2) { + log(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, int arg1, int arg2) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2); + } + } + + public void log(String format, Object arg1, Object arg2, Object arg3) { + log(BASIC_LEVEL, format, arg1, arg2, arg3); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3); + } + } + + public void log(String format, int arg1, int arg2, int arg3) { + log(BASIC_LEVEL, format, arg1, arg2, arg3); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, int arg1, int arg2, int arg3) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3); + } + } + + public void log(String format, Object arg1, Object arg2, Object arg3, Object arg4) { + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3, arg4); + } + } + + public void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3, arg4, arg5); + } + } + + public void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6); + } + } + + public void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + + public void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) { + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + + /** + * @see #log(int, String, Object) + */ + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + } + + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + } + + public void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + } + } + + public void log(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { + log(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + + public void log(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, Object arg8, Object arg9, Object arg10) { + if (currentScope != null) { + currentScope.log(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + } + } + + public void logv(String format, Object... args) { + logv(BASIC_LEVEL, format, args); + } + + /** + * Prints a message to the current debug scope's logging stream. This method must only be called + * if debugging scopes are {@linkplain DebugContext#areScopesEnabled() enabled} as it incurs + * allocation at the call site. If possible, call one of the other {@code log()} methods in this + * class that take a fixed number of parameters. + * + * @param format a format string + * @param args the arguments referenced by the format specifiers in {@code format} + */ + public void logv(int logLevel, String format, Object... args) { + if (currentScope == null) { + throw new InternalError("Use of Debug.logv() must be guarded by a test of Debug.isEnabled()"); + } + currentScope.log(logLevel, format, args); + } + + /** + * This override exists to catch cases when {@link #log(String, Object)} is called with one + * argument bound to a varargs method parameter. It will bind to this method instead of the + * single arg variant and produce a deprecation warning instead of silently wrapping the + * Object[] inside of another Object[]. + */ + @Deprecated + public void log(String format, Object[] args) { + assert false : "shouldn't use this"; + log(BASIC_LEVEL, format, args); + } + + /** + * This override exists to catch cases when {@link #log(int, String, Object)} is called with one + * argument bound to a varargs method parameter. It will bind to this method instead of the + * single arg variant and produce a deprecation warning instead of silently wrapping the + * Object[] inside of another Object[]. + */ + @Deprecated + public void log(int logLevel, String format, Object[] args) { + assert false : "shouldn't use this"; + logv(logLevel, format, args); + } + + /** + * Forces an unconditional dump. This method exists mainly for debugging. It can also be used to + * force a graph dump from IDEs that support invoking a Java method while at a breakpoint. + */ + public void forceDump(Object object, String format, Object... args) { + DebugConfig config = currentConfig; + Collection dumpHandlers; + boolean closeAfterDump; + if (config != null) { + dumpHandlers = config.dumpHandlers(); + closeAfterDump = false; + } else { + OptionValues options = getOptions(); + dumpHandlers = new ArrayList<>(); + for (DebugHandlersFactory factory : DebugHandlersFactory.LOADER) { + for (DebugHandler handler : factory.createHandlers(options)) { + if (handler instanceof DebugDumpHandler) { + dumpHandlers.add((DebugDumpHandler) handler); + } + } + } + closeAfterDump = true; + } + for (DebugDumpHandler dumpHandler : dumpHandlers) { + dumpHandler.dump(this, object, format, args); + if (closeAfterDump) { + dumpHandler.close(); + } + } + } + + public void dump(int dumpLevel, Object object, String msg) { + if (currentScope != null && currentScope.isDumpEnabled(dumpLevel)) { + currentScope.dump(dumpLevel, object, msg); + } + } + + public void dump(int dumpLevel, Object object, String format, Object arg) { + if (currentScope != null && currentScope.isDumpEnabled(dumpLevel)) { + currentScope.dump(dumpLevel, object, format, arg); + } + } + + public void dump(int dumpLevel, Object object, String format, Object arg1, Object arg2) { + if (currentScope != null && currentScope.isDumpEnabled(dumpLevel)) { + currentScope.dump(dumpLevel, object, format, arg1, arg2); + } + } + + public void dump(int dumpLevel, Object object, String format, Object arg1, Object arg2, Object arg3) { + if (currentScope != null && currentScope.isDumpEnabled(dumpLevel)) { + currentScope.dump(dumpLevel, object, format, arg1, arg2, arg3); + } + } + + /** + * This override exists to catch cases when {@link #dump(int, Object, String, Object)} is called + * with one argument bound to a varargs method parameter. It will bind to this method instead of + * the single arg variant and produce a deprecation warning instead of silently wrapping the + * Object[] inside of another Object[]. + */ + @Deprecated + public void dump(int dumpLevel, Object object, String format, Object[] args) { + assert false : "shouldn't use this"; + if (currentScope != null && currentScope.isDumpEnabled(dumpLevel)) { + currentScope.dump(dumpLevel, object, format, args); + } + } + + /** + * Calls all {@link DebugVerifyHandler}s in the current {@linkplain #getConfig() config} to + * perform verification on a given object. + * + * @param object object to verify + * @param message description of verification context + * + * @see DebugVerifyHandler#verify + */ + public void verify(Object object, String message) { + if (currentScope != null && currentScope.isVerifyEnabled()) { + currentScope.verify(object, message); + } + } + + /** + * Calls all {@link DebugVerifyHandler}s in the current {@linkplain #getConfig() config} to + * perform verification on a given object. + * + * @param object object to verify + * @param format a format string for the description of the verification context + * @param arg the argument referenced by the format specifiers in {@code format} + * + * @see DebugVerifyHandler#verify + */ + public void verify(Object object, String format, Object arg) { + if (currentScope != null && currentScope.isVerifyEnabled()) { + currentScope.verify(object, format, arg); + } + } + + /** + * This override exists to catch cases when {@link #verify(Object, String, Object)} is called + * with one argument bound to a varargs method parameter. It will bind to this method instead of + * the single arg variant and produce a deprecation warning instead of silently wrapping the + * Object[] inside of another Object[]. + */ + @Deprecated + public void verify(Object object, String format, Object[] args) { + assert false : "shouldn't use this"; + if (currentScope != null && currentScope.isVerifyEnabled()) { + currentScope.verify(object, format, args); + } + } + + /** + * Opens a new indentation level (by adding some spaces) based on the current indentation level. + * This should be used in a {@linkplain Indent try-with-resources} pattern. + * + * @return an object that reverts to the current indentation level when + * {@linkplain Indent#close() closed} or null if debugging is disabled + * @see #logAndIndent(int, String) + * @see #logAndIndent(int, String, Object) + */ + public Indent indent() { + if (currentScope != null) { + return currentScope.pushIndentLogger(); + } + return null; + } + + public Indent logAndIndent(String msg) { + return logAndIndent(BASIC_LEVEL, msg); + } + + /** + * A convenience function which combines {@link #log(String)} and {@link #indent()}. + * + * @param msg the message to log + * @return an object that reverts to the current indentation level when + * {@linkplain Indent#close() closed} or null if debugging is disabled + */ + public Indent logAndIndent(int logLevel, String msg) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, msg); + } + return null; + } + + public Indent logAndIndent(String format, Object arg) { + return logAndIndent(BASIC_LEVEL, format, arg); + } + + /** + * A convenience function which combines {@link #log(String, Object)} and {@link #indent()}. + * + * @param format a format string + * @param arg the argument referenced by the format specifiers in {@code format} + * @return an object that reverts to the current indentation level when + * {@linkplain Indent#close() closed} or null if debugging is disabled + */ + public Indent logAndIndent(int logLevel, String format, Object arg) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg); + } + return null; + } + + public Indent logAndIndent(String format, int arg) { + return logAndIndent(BASIC_LEVEL, format, arg); + } + + /** + * A convenience function which combines {@link #log(String, Object)} and {@link #indent()}. + * + * @param format a format string + * @param arg the argument referenced by the format specifiers in {@code format} + * @return an object that reverts to the current indentation level when + * {@linkplain Indent#close() closed} or null if debugging is disabled + */ + public Indent logAndIndent(int logLevel, String format, int arg) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg); + } + return null; + } + + public Indent logAndIndent(String format, int arg1, Object arg2) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, int arg1, Object arg2) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2); + } + return null; + } + + public Indent logAndIndent(String format, Object arg1, int arg2) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, Object arg1, int arg2) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2); + } + return null; + } + + public Indent logAndIndent(String format, int arg1, int arg2) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, int arg1, int arg2) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2); + } + return null; + } + + public Indent logAndIndent(String format, Object arg1, Object arg2) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2); + } + return null; + } + + public Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3); + } + return null; + } + + public Indent logAndIndent(String format, int arg1, int arg2, int arg3) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, int arg1, int arg2, int arg3) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3); + } + return null; + } + + public Indent logAndIndent(String format, Object arg1, int arg2, int arg3) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, Object arg1, int arg2, int arg3) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3); + } + return null; + } + + public Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3, arg4); + } + return null; + } + + public Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3, arg4, arg5); + } + return null; + } + + public Indent logAndIndent(String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { + return logAndIndent(BASIC_LEVEL, format, arg1, arg2, arg3, arg4, arg5, arg6); + } + + /** + * @see #logAndIndent(int, String, Object) + */ + public Indent logAndIndent(int logLevel, String format, Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) { + if (currentScope != null && isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, arg1, arg2, arg3, arg4, arg5, arg6); + } + return null; + } + + /** + * A convenience function which combines {@link #logv(int, String, Object...)} and + * {@link #indent()}. + * + * @param format a format string + * @param args the arguments referenced by the format specifiers in {@code format} + * @return an object that reverts to the current indentation level when + * {@linkplain Indent#close() closed} or null if debugging is disabled + */ + public Indent logvAndIndent(int logLevel, String format, Object... args) { + if (currentScope != null) { + if (isLogEnabled(logLevel)) { + return logvAndIndentInternal(logLevel, format, args); + } + return null; + } + throw new InternalError("Use of Debug.logvAndIndent() must be guarded by a test of Debug.isEnabled()"); + } + + private Indent logvAndIndentInternal(int logLevel, String format, Object... args) { + assert currentScope != null && isLogEnabled(logLevel) : "must have checked Debug.isLogEnabled()"; + currentScope.log(logLevel, format, args); + return currentScope.pushIndentLogger(); + } + + /** + * This override exists to catch cases when {@link #logAndIndent(String, Object)} is called with + * one argument bound to a varargs method parameter. It will bind to this method instead of the + * single arg variant and produce a deprecation warning instead of silently wrapping the + * Object[] inside of another Object[]. + */ + @Deprecated + public void logAndIndent(String format, Object[] args) { + assert false : "shouldn't use this"; + logAndIndent(BASIC_LEVEL, format, args); + } + + /** + * This override exists to catch cases when {@link #logAndIndent(int, String, Object)} is called + * with one argument bound to a varargs method parameter. It will bind to this method instead of + * the single arg variant and produce a deprecation warning instead of silently wrapping the + * Object[] inside of another Object[]. + */ + @Deprecated + public void logAndIndent(int logLevel, String format, Object[] args) { + assert false : "shouldn't use this"; + logvAndIndent(logLevel, format, args); + } + + public Iterable context() { + if (currentScope != null) { + return currentScope.getCurrentContext(); + } else { + return Collections.emptyList(); + } + } + + @SuppressWarnings("unchecked") + public List contextSnapshot(Class clazz) { + if (currentScope != null) { + List result = new ArrayList<>(); + for (Object o : context()) { + if (clazz.isInstance(o)) { + result.add((T) o); + } + } + return result; + } else { + return Collections.emptyList(); + } + } + + /** + * Searches the current debug scope, bottom up, for a context object that is an instance of a + * given type. The first such object found is returned. + */ + @SuppressWarnings("unchecked") + public T contextLookup(Class clazz) { + if (currentScope != null) { + for (Object o : context()) { + if (clazz.isInstance(o)) { + return ((T) o); + } + } + } + return null; + } + + /** + * Searches the current debug scope, top down, for a context object that is an instance of a + * given type. The first such object found is returned. + */ + @SuppressWarnings("unchecked") + public T contextLookupTopdown(Class clazz) { + if (currentScope != null) { + T found = null; + for (Object o : context()) { + if (clazz.isInstance(o)) { + found = (T) o; + } + } + return found; + } + return null; + } + + /** + * Creates a {@linkplain MemUseTrackerKey memory use tracker}. + */ + public static MemUseTrackerKey memUseTracker(CharSequence name) { + return createMemUseTracker("%s", name, null); + } + + /** + * Creates a debug memory use tracker. Invoking this method is equivalent to: + * + *
      +     * Debug.memUseTracker(format, arg, null)
      +     * 
      + * + * except that the string formatting only happens if mem tracking is enabled. + * + * @see #counter(String, Object, Object) + */ + public static MemUseTrackerKey memUseTracker(String format, Object arg) { + return createMemUseTracker(format, arg, null); + } + + /** + * Creates a debug memory use tracker. Invoking this method is equivalent to: + * + *
      +     * Debug.memUseTracker(String.format(format, arg1, arg2))
      +     * 
      + * + * except that the string formatting only happens if memory use tracking is enabled. In + * addition, each argument is subject to the following type based conversion before being passed + * as an argument to {@link String#format(String, Object...)}: + * + *
      +     *     Type          | Conversion
      +     * ------------------+-----------------
      +     *  java.lang.Class  | arg.getSimpleName()
      +     *                   |
      +     * 
      + * + * @see #memUseTracker(CharSequence) + */ + public static MemUseTrackerKey memUseTracker(String format, Object arg1, Object arg2) { + return createMemUseTracker(format, arg1, arg2); + } + + private static MemUseTrackerKey createMemUseTracker(String format, Object arg1, Object arg2) { + return new MemUseTrackerKeyImpl(format, arg1, arg2); + } + + /** + * Creates a {@linkplain CounterKey counter}. + */ + public static CounterKey counter(CharSequence name) { + return createCounter("%s", name, null); + } + + /** + * Gets a tally of the metric values in this context and a given tally. + * + * @param tally the tally to which the metrics should be added + * @return a tally of the metric values in this context and {@code tally}. This will be + * {@code tally} if this context has no metric values or {@code tally} is wide enough to + * hold all the metric values in this context otherwise it will be a new array. + */ + public long[] addValuesTo(long[] tally) { + if (metricValues == null) { + return tally; + } + if (tally == null) { + return metricValues.clone(); + } else if (metricValues.length >= tally.length) { + long[] newTally = metricValues.clone(); + for (int i = 0; i < tally.length; i++) { + newTally[i] += tally[i]; + } + return newTally; + } else { + for (int i = 0; i < metricValues.length; i++) { + tally[i] += metricValues[i]; + } + return tally; + } + } + + /** + * Creates and returns a sorted map from metric names to their values in {@code values}. + * + * @param values values for metrics in the {@link KeyRegistry}. + */ + public static EconomicMap convertValuesToKeyValueMap(long[] values) { + List keys = KeyRegistry.getKeys(); + Collections.sort(keys, MetricKey.NAME_COMPARATOR); + EconomicMap res = EconomicMap.create(keys.size()); + for (MetricKey key : keys) { + int index = ((AbstractKey) key).getIndex(); + if (index >= values.length) { + res.put(key, 0L); + } else { + res.put(key, values[index]); + } + } + return res; + } + + void setMetricValue(int keyIndex, long l) { + ensureMetricValuesSize(keyIndex); + metricValues[keyIndex] = l; + } + + long getMetricValue(int keyIndex) { + if (metricValues == null || metricValues.length <= keyIndex) { + return 0L; + } + return metricValues[keyIndex]; + } + + private void ensureMetricValuesSize(int index) { + if (metricValues == null) { + metricValues = new long[index + 1]; + } + if (metricValues.length <= index) { + metricValues = Arrays.copyOf(metricValues, index + 1); + } + } + + public static String applyFormattingFlagsAndWidth(String s, int flags, int width) { + if (flags == 0 && width < 0) { + return s; + } + StringBuilder sb = new StringBuilder(s); + + // apply width and justification + int len = sb.length(); + if (len < width) { + for (int i = 0; i < width - len; i++) { + if ((flags & LEFT_JUSTIFY) == LEFT_JUSTIFY) { + sb.append(' '); + } else { + sb.insert(0, ' '); + } + } + } + + String res = sb.toString(); + if ((flags & UPPERCASE) == UPPERCASE) { + res = res.toUpperCase(); + } + return res; + } + + /** + * Creates a debug counter. Invoking this method is equivalent to: + * + *
      +     * Debug.counter(format, arg, null)
      +     * 
      + * + * except that the string formatting only happens if count is enabled. + * + * @see #counter(String, Object, Object) + */ + public static CounterKey counter(String format, Object arg) { + return createCounter(format, arg, null); + } + + /** + * Creates a debug counter. Invoking this method is equivalent to: + * + *
      +     * Debug.counter(String.format(format, arg1, arg2))
      +     * 
      + * + * except that the string formatting only happens if count is enabled. In addition, each + * argument is subject to the following type based conversion before being passed as an argument + * to {@link String#format(String, Object...)}: + * + *
      +     *     Type          | Conversion
      +     * ------------------+-----------------
      +     *  java.lang.Class  | arg.getSimpleName()
      +     *                   |
      +     * 
      + * + * @see #counter(CharSequence) + */ + public static CounterKey counter(String format, Object arg1, Object arg2) { + return createCounter(format, arg1, arg2); + } + + private static CounterKey createCounter(String format, Object arg1, Object arg2) { + return new CounterKeyImpl(format, arg1, arg2); + } + + public DebugConfig getConfig() { + return currentConfig; + } + + /** + * Creates a {@linkplain TimerKey timer}. + *

      + * A disabled timer has virtually no overhead. + */ + public static TimerKey timer(CharSequence name) { + return createTimer("%s", name, null); + } + + /** + * Creates a debug timer. Invoking this method is equivalent to: + * + *

      +     * Debug.timer(format, arg, null)
      +     * 
      + * + * except that the string formatting only happens if timing is enabled. + * + * @see #timer(String, Object, Object) + */ + public static TimerKey timer(String format, Object arg) { + return createTimer(format, arg, null); + } + + /** + * Creates a debug timer. Invoking this method is equivalent to: + * + *
      +     * Debug.timer(String.format(format, arg1, arg2))
      +     * 
      + * + * except that the string formatting only happens if timing is enabled. In addition, each + * argument is subject to the following type based conversion before being passed as an argument + * to {@link String#format(String, Object...)}: + * + *
      +     *     Type          | Conversion
      +     * ------------------+-----------------
      +     *  java.lang.Class  | arg.getSimpleName()
      +     *                   |
      +     * 
      + * + * @see #timer(CharSequence) + */ + public static TimerKey timer(String format, Object arg1, Object arg2) { + return createTimer(format, arg1, arg2); + } + + /** + * There are paths where construction of formatted class names are common and the code below is + * surprisingly expensive, so compute it once and cache it. + */ + private static final ClassValue formattedClassName = new ClassValue() { + @Override + protected String computeValue(Class c) { + final String simpleName = c.getSimpleName(); + Class enclosingClass = c.getEnclosingClass(); + if (enclosingClass != null) { + String prefix = ""; + while (enclosingClass != null) { + prefix = enclosingClass.getSimpleName() + "_" + prefix; + enclosingClass = enclosingClass.getEnclosingClass(); + } + return prefix + simpleName; + } else { + return simpleName; + } + } + }; + + public static Object convertFormatArg(Object arg) { + if (arg instanceof Class) { + return formattedClassName.get((Class) arg); + } + return arg; + } + + static String formatDebugName(String format, Object arg1, Object arg2) { + return String.format(format, convertFormatArg(arg1), convertFormatArg(arg2)); + } + + private static TimerKey createTimer(String format, Object arg1, Object arg2) { + return new TimerKeyImpl(format, arg1, arg2); + } + + /** + * Represents a debug scope entered by {@link DebugContext#scope(Object)} or + * {@link DebugContext#sandbox(CharSequence, DebugConfig, Object...)}. Leaving the scope is + * achieved via {@link #close()}. + */ + public interface Scope extends AutoCloseable { + /** + * Gets the names of this scope and its ancestors separated by {@code '.'}. + */ + String getQualifiedName(); + + Iterable getCurrentContext(); + + @Override + void close(); + } + + boolean isTimerEnabled(TimerKeyImpl key) { + if (!metricsEnabled) { + // Pulling this common case out of `isTimerEnabledSlow` + // gives C1 a better chance to inline this method. + return false; + } + return isTimerEnabledSlow(key); + } + + private boolean isTimerEnabledSlow(AbstractKey key) { + if (currentScope != null && currentScope.isTimeEnabled()) { + return true; + } + if (immutable.listMetrics) { + key.ensureInitialized(); + } + assert checkNoConcurrentAccess(); + EconomicSet unscoped = immutable.unscopedTimers; + return unscoped != null && (unscoped.isEmpty() || unscoped.contains(key.getName())); + } + + /** + * Determines if a given timer is enabled in the current scope. + */ + boolean isCounterEnabled(CounterKeyImpl key) { + if (!metricsEnabled) { + // Pulling this common case out of `isCounterEnabledSlow` + // gives C1 a better chance to inline this method. + return false; + } + return isCounterEnabledSlow(key); + } + + private boolean isCounterEnabledSlow(AbstractKey key) { + if (currentScope != null && currentScope.isCountEnabled()) { + return true; + } + if (immutable.listMetrics) { + key.ensureInitialized(); + } + assert checkNoConcurrentAccess(); + EconomicSet unscoped = immutable.unscopedCounters; + return unscoped != null && (unscoped.isEmpty() || unscoped.contains(key.getName())); + } + + boolean isMemUseTrackerEnabled(MemUseTrackerKeyImpl key) { + if (!metricsEnabled) { + // Pulling this common case out of `isMemUseTrackerEnabledSlow` + // gives C1 a better chance to inline this method. + return false; + } + return isMemUseTrackerEnabledSlow(key); + } + + private boolean isMemUseTrackerEnabledSlow(AbstractKey key) { + if (currentScope != null && currentScope.isMemUseTrackingEnabled()) { + return true; + } + if (immutable.listMetrics) { + key.ensureInitialized(); + } + assert checkNoConcurrentAccess(); + EconomicSet unscoped = immutable.unscopedMemUseTrackers; + return unscoped != null && (unscoped.isEmpty() || unscoped.contains(key.getName())); + } + + public boolean areMetricsEnabled() { + return metricsEnabled; + } + + @Override + public void close() { + closeDumpHandlers(false); + if (description != null) { + printMetrics(description); + } + if (metricsEnabled && globalMetrics != null && metricValues != null) { + globalMetrics.add(this); + } + metricValues = null; + } + + public void closeDumpHandlers(boolean ignoreErrors) { + if (currentConfig != null) { + currentConfig.closeDumpHandlers(ignoreErrors); + } + } + + /** + * Records how many times a given method has been compiled. + */ + private static EconomicMap compilations; + + /** + * Maintains maximum buffer size used by {@link #printMetrics(Description)} to minimize buffer + * resizing during subsequent calls to this method. + */ + private static int metricsBufSize = 50_000; + + /** + * Flag that allows the first call to {@link #printMetrics(Description)} to delete the file that + * will be appended to. + */ + private static boolean metricsFileDeleteCheckPerformed; + + /** + * Prints metric values in this object to the file (if any) specified by + * {@link DebugOptions#MetricsFile}. + */ + public void printMetrics(Description desc) { + if (metricValues == null) { + return; + } + String metricsFile = DebugOptions.MetricsFile.getValue(getOptions()); + if (metricsFile != null) { + // Use identity to distinguish methods that have been redefined + // or loaded by different class loaders. + Object compilable = desc.compilable; + Integer identity = System.identityHashCode(compilable); + int compilationNr; + synchronized (PRINT_METRICS_LOCK) { + if (!metricsFileDeleteCheckPerformed) { + metricsFileDeleteCheckPerformed = true; + File file = new File(metricsFile); + if (file.exists()) { + // This can return false in case something like /dev/stdout + // is specified. If the file is unwriteable, the file open + // below will fail. + file.delete(); + } + } + if (compilations == null) { + compilationNr = 0; + compilations = EconomicMap.create(); + } else { + Integer value = compilations.get(identity); + compilationNr = value == null ? 0 : value + 1; + } + compilations.put(identity, compilationNr); + } + + // Release the lock while generating the content to reduce contention. + // This means `compilationNr` fields may show up out of order in the file. + ByteArrayOutputStream baos = new ByteArrayOutputStream(metricsBufSize); + PrintStream out = new PrintStream(baos); + if (metricsFile.endsWith(".csv") || metricsFile.endsWith(".CSV")) { + printMetricsCSV(out, compilable, identity, compilationNr, desc.identifier); + } else { + printMetrics(out, compilable, identity, compilationNr, desc.identifier); + } + + byte[] content = baos.toByteArray(); + Path path = Paths.get(metricsFile); + synchronized (PRINT_METRICS_LOCK) { + metricsBufSize = Math.max(metricsBufSize, content.length); + try { + Files.write(path, content, StandardOpenOption.CREATE, StandardOpenOption.APPEND); + } catch (IOException e) { + } + } + } + + } + + /** + * Lock to serialize writes to {@link DebugOptions#MetricsFile}. + */ + private static final Object PRINT_METRICS_LOCK = new Object(); + + /** + * Appends metrics in CSV format to {@code out} for a single method compilation. + * + * @param identity the identity hash code of {@code compilable} + * @param compilationNr where this compilation lies in the ordered sequence of all compilations + * identified by {@code identity} + * @param compilationId the runtime issued identifier for the compilation + */ + private void printMetricsCSV(PrintStream out, Object compilable, Integer identity, int compilationNr, String compilationId) { + String compilableName = compilable instanceof JavaMethod ? ((JavaMethod) compilable).format("%H.%n(%p)%R") : String.valueOf(compilable); + String csvFormat = CSVUtil.buildFormatString("%s", "%s", "%d", "%s"); + String format = String.format(csvFormat, CSVUtil.Escape.escapeArgs(compilableName, identity, compilationNr, compilationId)); + char sep = CSVUtil.SEPARATOR; + format += sep + "%s" + sep + "%s" + sep + "%s"; + for (MetricKey key : KeyRegistry.getKeys()) { + int index = ((AbstractKey) key).getIndex(); + if (index < metricValues.length) { + Pair valueAndUnit = key.toCSVFormat(metricValues[index]); + CSVUtil.Escape.println(out, format, CSVUtil.Escape.escape(key.getName()), valueAndUnit.getLeft(), valueAndUnit.getRight()); + } + } + } + + /** + * Appends metrics in a human readable format to {@code out} for a single method compilation. + * + * @param identity the identity hash code of {@code compilable} + * @param compilationNr where this compilation lies in the ordered sequence of all compilations + * identified by {@code identity} + * @param compilationId the runtime issued identifier for the compilation + */ + private void printMetrics(PrintStream out, Object compilable, Integer identity, int compilationNr, String compilationId) { + String compilableName = compilable instanceof JavaMethod ? ((JavaMethod) compilable).format("%H.%n(%p)%R") : String.valueOf(compilable); + int maxKeyWidth = compilableName.length(); + SortedMap res = new TreeMap<>(); + for (MetricKey key : KeyRegistry.getKeys()) { + int index = ((AbstractKey) key).getIndex(); + if (index < metricValues.length && metricValues[index] != 0) { + String name = key.getName(); + long value = metricValues[index]; + String valueString; + if (key instanceof TimerKey) { + // Report timers in ms + TimerKey timer = (TimerKey) key; + long ms = timer.getTimeUnit().toMillis(value); + if (ms == 0) { + continue; + } + valueString = ms + "ms"; + } else { + valueString = String.valueOf(value); + } + res.put(name, valueString); + maxKeyWidth = Math.max(maxKeyWidth, name.length()); + } + } + + String title = String.format("%s [id:%s compilation:%d compilation_id:%s]", compilableName, identity, compilationNr, compilationId); + out.println(new String(new char[title.length()]).replace('\0', '#')); + out.printf("%s%n", title); + out.println(new String(new char[title.length()]).replace('\0', '~')); + + for (Map.Entry e : res.entrySet()) { + out.printf("%-" + String.valueOf(maxKeyWidth) + "s = %20s%n", e.getKey(), e.getValue()); + } + out.println(); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugCounter.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugCounter.java deleted file mode 100644 index f0e3f6be951..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugCounter.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug; - -/** - * A counter for some value of interest. - */ -public interface DebugCounter { - - /** - * Adds 1 to this counter if counting is {@link Debug#isCountEnabled() enabled} or this is an - * {@linkplain #isConditional() unconditional} counter. - */ - void increment(); - - /** - * Adds {@code value} to this counter if counting is {@link Debug#isCountEnabled() enabled} or - * this is an {@linkplain #isConditional() unconditional} counter. - */ - void add(long value); - - /** - * Sets a flag determining if this counter is only enabled if counting is - * {@link Debug#isCountEnabled() enabled}. - */ - void setConditional(boolean flag); - - /** - * Determines if this counter is only enabled if counting is {@link Debug#isCountEnabled() - * enabled}. - */ - boolean isConditional(); - - /** - * Gets the current value of this counter. - */ - long getCurrentValue(); - - /** - * Determines if this counter is enabled (either conditionally or unconditionally). - */ - default boolean isEnabled() { - return !isConditional() || Debug.isCountEnabled(); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugDumpHandler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugDumpHandler.java index 3b52c31215b..e04ecd082df 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugDumpHandler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugDumpHandler.java @@ -24,15 +24,34 @@ package org.graalvm.compiler.debug; import java.io.Closeable; -public interface DebugDumpHandler extends Closeable { +/** + * Interface implemented by classes that provide an external visualization of selected object types + * such as compiler graphs and nodes. The format and client required to consume the visualizations + * is determined by the implementation. For example, a dumper may convert a compiler node to a human + * readable string and print it to the console. A more sophisticated dumper may serialize a compiler + * graph and send it over the network to a tool (e.g., https://github.com/graalvm/visualizer) that + * can display graphs. + */ +public interface DebugDumpHandler extends Closeable, DebugHandler { - void dump(Object object, String message); + /** + * If the type of {@code object} is supported by this dumper, then a representation of + * {@code object} is sent to some consumer in a format determined by this object. + * + * @param debug the debug context requesting the dump + * @param object the object to be dumped + * @param format a format string specifying a title that describes the context of the dump + * (e.g., the compiler phase in which request is made) + * @param arguments arguments referenced by the format specifiers in {@code format} + */ + void dump(DebugContext debug, Object object, String format, Object... arguments); /** * Flushes and releases resources managed by this dump handler. A subsequent call to - * {@link #dump(Object, String)} will create and open new resources. That is, this method can be - * used to reset the handler. + * {@link #dump} will create and open new resources. That is, this method can be used to reset + * the handler. */ @Override - void close(); + default void close() { + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugEnvironment.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugEnvironment.java deleted file mode 100644 index 9a15e241822..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugEnvironment.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug; - -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Log; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Count; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodFilter; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Time; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.TrackMemUse; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Verify; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodMeter; - -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.List; - -import org.graalvm.compiler.serviceprovider.GraalServices; - -import jdk.vm.ci.runtime.JVMCI; - -public class DebugEnvironment { - - public static GraalDebugConfig initialize(PrintStream log, Object... extraArgs) { - // Initialize JVMCI before loading class Debug - JVMCI.initialize(); - if (!Debug.isEnabled()) { - log.println("WARNING: Scope debugging needs to be enabled with -esa"); - return null; - } - List dumpHandlers = new ArrayList<>(); - List verifyHandlers = new ArrayList<>(); - GraalDebugConfig debugConfig = new GraalDebugConfig(Log.getValue(), Count.getValue(), TrackMemUse.getValue(), Time.getValue(), Dump.getValue(), Verify.getValue(), MethodFilter.getValue(), - MethodMeter.getValue(), - log, dumpHandlers, verifyHandlers); - - for (DebugConfigCustomizer customizer : GraalServices.load(DebugConfigCustomizer.class)) { - customizer.customize(debugConfig, extraArgs); - } - - Debug.setConfig(debugConfig); - return debugConfig; - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugFilter.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugFilter.java index 0345a548a09..5a9f522ac84 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugFilter.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugFilter.java @@ -25,44 +25,43 @@ package org.graalvm.compiler.debug; import java.util.Arrays; import java.util.regex.Pattern; -import org.graalvm.compiler.debug.GraalDebugConfig.Options; -import org.graalvm.compiler.debug.internal.DebugScope; +import org.graalvm.compiler.debug.DebugContext.Scope; /** - * Implements the filter specified by the {@link Options#Dump}, {@link Options#Log}, - * {@link Options#Count},{@link Options#MethodMeter} and {@link Options#Time} options. + * Implements the filter specified by the {@link DebugOptions#Dump}, {@link DebugOptions#Log}, + * {@link DebugOptions#Count} and {@link DebugOptions#Time} options. *

      * These options enable the associated debug facility if their filter matches the - * {@linkplain DebugScope#getQualifiedName() name} of the {@linkplain Debug#currentScope() current - * scope}. For the {@link Options#Dump} and {@link Options#Log} options, the log or dump level is - * set. The {@link Options#Count},{@link Options#MethodMeter} and {@link Options#Time} options don't - * have a level, for them {@code level = 0} means disabled and a {@code level > 0} means enabled. + * {@linkplain Scope#getQualifiedName() name} of the current scope. For the + * {@link DebugOptions#Dump} and {@link DebugOptions#Log} options, the log or dump level is set. The + * {@link DebugOptions#Count} and {@link DebugOptions#Time} options don't have a level, for them + * {@code level = 0} means disabled and a {@code level > 0} means enabled. *

      * A filter is a list of comma-separated terms of the form {@code [:]}. {@code * } is interpreted as a glob pattern if it contains a "*" or "?" character. Otherwise, it * is interpreted as a substring. If {@code } is empty, it matches every scope. If {@code : - * } is omitted, it defaults to {@link Debug#BASIC_LOG_LEVEL}. The term {@code ~} is - * a shorthand for {@code :0} to disable a debug facility for a pattern. + * } is omitted, it defaults to {@link DebugContext#BASIC_LEVEL}. The term {@code ~} + * is a shorthand for {@code :0} to disable a debug facility for a pattern. *

      * The resulting log level of a scope is determined by the last matching term. If no term * matches, the log level is 0 (disabled). A filter with no terms matches every scope with a log - * level of {@link Debug#BASIC_LOG_LEVEL}. + * level of {@link DebugContext#BASIC_LEVEL}. * *

      Examples of filters

      * *
        *
      • (empty string)
        - * Matches any scope with log level {@link Debug#BASIC_LOG_LEVEL}. + * Matches any scope with log level {@link DebugContext#BASIC_LEVEL}. * *
      • {@code :1}
        * Matches any scope with log level 1. * *
      • {@code *}
        - * Matches any scope with log level {@link Debug#BASIC_LOG_LEVEL}. + * Matches any scope with log level {@link DebugContext#BASIC_LEVEL}. * *
      • {@code CodeGen,CodeInstall}
        * Matches scopes containing "CodeGen" or "CodeInstall", both with log level - * {@link Debug#BASIC_LOG_LEVEL}. + * {@link DebugContext#BASIC_LEVEL}. * *
      • {@code CodeGen:2,CodeInstall:1}
        * Matches scopes containing "CodeGen" with log level 2, or "CodeInstall" with log level 1. @@ -74,10 +73,10 @@ import org.graalvm.compiler.debug.internal.DebugScope; * Matches all scopes with log level 1, except those containing "Dead". * *
      • {@code Code*}
        - * Matches scopes starting with "Code" with log level {@link Debug#BASIC_LOG_LEVEL}. + * Matches scopes starting with "Code" with log level {@link DebugContext#BASIC_LEVEL}. * *
      • {@code Code,~Dead}
        - * Matches scopes containing "Code" but not "Dead", with log level {@link Debug#BASIC_LOG_LEVEL}. + * Matches scopes containing "Code" but not "Dead", with log level {@link DebugContext#BASIC_LEVEL}. *
      */ final class DebugFilter { @@ -108,7 +107,7 @@ final class DebugFilter { level = 0; } else { pattern = t; - level = Debug.BASIC_LOG_LEVEL; + level = DebugContext.BASIC_LEVEL; } } else { pattern = t.substring(0, idx); @@ -119,13 +118,13 @@ final class DebugFilter { } catch (NumberFormatException e) { switch (levelString) { case "basic": - level = Debug.BASIC_LOG_LEVEL; + level = DebugContext.BASIC_LEVEL; break; case "info": - level = Debug.INFO_LOG_LEVEL; + level = DebugContext.INFO_LEVEL; break; case "verbose": - level = Debug.VERBOSE_LOG_LEVEL; + level = DebugContext.VERBOSE_LEVEL; break; default: throw new IllegalArgumentException("Unknown dump level: \"" + levelString + "\" expected basic, info, verbose or an integer"); @@ -133,7 +132,7 @@ final class DebugFilter { } } else { - level = Debug.BASIC_LOG_LEVEL; + level = DebugContext.BASIC_LEVEL; } } @@ -147,7 +146,7 @@ final class DebugFilter { */ public int matchLevel(String input) { if (terms == null) { - return Debug.BASIC_LOG_LEVEL; + return DebugContext.BASIC_LEVEL; } else { int level = 0; for (Term t : terms) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TopLevelDebugConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugHandler.java similarity index 78% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TopLevelDebugConfig.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugHandler.java index dc692f6fc3a..7608ced4f97 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TopLevelDebugConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -23,9 +23,8 @@ package org.graalvm.compiler.debug; /** - * A marker class for a scoped debug configuration covering a compilation region. Useful for - * programmatically enabling debug config features. - * + * This interface exists to unify {@link DebugDumpHandler} and {@link DebugVerifyHandler} for the + * sake of {@link DebugHandlersFactory#createHandlers}. */ -public class TopLevelDebugConfig extends DelegatingDebugConfig { +public interface DebugHandler { } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/Salver.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugHandlersFactory.java similarity index 58% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/Salver.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugHandlersFactory.java index 79a343f1580..62fb5668198 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/Salver.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugHandlersFactory.java @@ -20,28 +20,31 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.salver; +package org.graalvm.compiler.debug; -import static org.graalvm.compiler.salver.SalverOptions.SalverAddress; -import static org.graalvm.compiler.salver.SalverOptions.SalverPort; +import java.util.Iterator; +import java.util.List; -import java.net.InetSocketAddress; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.serviceprovider.GraalServices; -import org.graalvm.compiler.salver.util.ECIDUtil; - -public final class Salver { +/** + * Factory for creating {@link DebugHandler}s. + */ +public interface DebugHandlersFactory { /** - * The Execution Context Identifier is a unique identifier that simplifies the grouping of - * events created in different DumpHandlers or Threads. It should be added as a special property - * to all :begin trace events. + * Creates {@link DebugHandler}s based on {@code options}. */ - public static final String ECID = ECIDUtil.random(); + List createHandlers(OptionValues options); - private Salver() { - } - - public static InetSocketAddress getSocketAddress() { - return new InetSocketAddress(SalverAddress.getValue(), SalverPort.getValue()); - } + /** + * Loads {@link DebugHandlersFactory}s on demand via {@link GraalServices#load(Class)}. + */ + Iterable LOADER = new Iterable() { + @Override + public Iterator iterator() { + return GraalServices.load(DebugHandlersFactory.class).iterator(); + } + }; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugHistogram.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugHistogram.java deleted file mode 100644 index bd28c6f5515..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugHistogram.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug; - -import java.util.List; - -/** - * Facility for recording value frequencies. - */ -public interface DebugHistogram { - - /** - * Gets the name specified when this objected was {@linkplain Debug#createHistogram(String) - * created}. - */ - String getName(); - - /** - * Increments the count for a given value. - */ - void add(Object value); - - void add(Object value, long count); - - /** - * A value and a frequency. The ordering imposed by {@link #compareTo(CountedValue)} places - * values with higher frequencies first. - */ - class CountedValue implements Comparable { - - private long count; - private final Object value; - - public CountedValue(long count, Object value) { - this.count = count; - this.value = value; - } - - @Override - public int compareTo(CountedValue o) { - if (count < o.count) { - return 1; - } else if (count > o.count) { - return -1; - } - return 0; - } - - @Override - public String toString() { - return count + " -> " + value; - } - - public void inc() { - count++; - } - - public void add(long n) { - count += n; - } - - public long getCount() { - return count; - } - - public Object getValue() { - return value; - } - } - - /** - * Gets a list of the counted values, sorted in descending order of frequency. - */ - List getValues(); - - /** - * Interface for a service that can render a visualization of a histogram. - */ - public interface Printer { - - void print(DebugHistogram histogram); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMemUseTracker.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMemUseTracker.java index 8ce52f65679..90b91b0a9f5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMemUseTracker.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMemUseTracker.java @@ -22,11 +22,9 @@ */ package org.graalvm.compiler.debug; -import com.sun.management.ThreadMXBean; - /** - * Tracks memory usage within a scope using {@link ThreadMXBean}. This facility should be employed - * using the try-with-resources pattern: + * Tracks memory usage within a scope using {@link com.sun.management.ThreadMXBean}. This facility + * should be employed using the try-with-resources pattern: * *
        * try (DebugMemUseTracker.Closeable a = memUseTracker.start()) {
      @@ -38,7 +36,7 @@ public interface DebugMemUseTracker {
       
           /**
            * Creates a point from which memory usage will be recorded if memory use tracking is
      -     * {@linkplain Debug#isMemUseTrackingEnabled() enabled}.
      +     * {@linkplain DebugContext#isMemUseTrackingEnabled() enabled}.
            *
            * @return an object that must be closed once the activity has completed to add the memory used
            *         since this call to the total for this tracker
      diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMethodMetrics.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMethodMetrics.java
      deleted file mode 100644
      index 6877926a41d..00000000000
      --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMethodMetrics.java
      +++ /dev/null
      @@ -1,124 +0,0 @@
      -/*
      - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
      - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      - *
      - * This code is free software; you can redistribute it and/or modify it
      - * under the terms of the GNU General Public License version 2 only, as
      - * published by the Free Software Foundation.
      - *
      - * This code is distributed in the hope that it will be useful, but WITHOUT
      - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      - * version 2 for more details (a copy is included in the LICENSE file that
      - * accompanied this code).
      - *
      - * You should have received a copy of the GNU General Public License version
      - * 2 along with this work; if not, write to the Free Software Foundation,
      - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
      - *
      - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
      - * or visit www.oracle.com if you need additional information or have any
      - * questions.
      - */
      -package org.graalvm.compiler.debug;
      -
      -import jdk.vm.ci.meta.ResolvedJavaMethod;
      -
      -/**
      - * A set of debug metrics for all compilations of a {@link ResolvedJavaMethod}. A method metrics
      - * object is a container for several metrics per compilation of a method {@code >}. Metrics are stored on a per-method per-compilation basis.
      - *
      - * 
      - * DebugMethodMetrics m = Debug.methodMetrics(method);
      - * m.incrementMetric("MyPerCompilationmetric");
      - * 
      - * - * In contrast to global metrics like {@link DebugCounter}, {@link DebugTimer} or - * {@linkplain DebugMemUseTracker}, method compilation metrics are always associated with a - * {@link ResolvedJavaMethod}. - */ -public interface DebugMethodMetrics { - - /** - * Adds {@code value} to the metric for the current compilation associated with - * {@code metricName}. If the metric is yet undefined for the current compilation a new metric - * for the given name is defined and the value for it is set to {@code value}. - * - * @param metricName the name for the metric to be incremented - * @param value the value to add to the metric defined by name - */ - void addToMetric(long value, String metricName); - - /** - * @see #addToMetric(long, String) - */ - void addToMetric(long value, String format, Object arg1); - - /** - * @see #addToMetric(long, String) - */ - void addToMetric(long value, String format, Object arg1, Object arg2); - - /** - * @see #addToMetric(long, String) - */ - void addToMetric(long value, String format, Object arg1, Object arg2, Object arg3); - - /** - * Adds {@code 1} to the metric for the current compilation associated with {@code metricName}. - * If the metric is yet undefined for the current compilation a new metric for the given name is - * defined and the value for it is set to {@code value}. - * - * @param metricName the name for the metric to be incremented - */ - void incrementMetric(String metricName); - - /** - * @see #incrementMetric(String) - */ - void incrementMetric(String format, Object arg1); - - /** - * @see #incrementMetric(String) - */ - void incrementMetric(String format, Object arg1, Object arg2); - - /** - * @see #incrementMetric(String) - */ - void incrementMetric(String format, Object arg1, Object arg2, Object arg3); - - /** - * Gets the value of the metric for the current compilation associated with the - * {@code metricName} . If the metric is yet undefined for the current compilation {@code 0} is - * returned instead. - * - * @param metricName the name of the metric for which the value will be returned - * @return the value of the metric for the given compilation or {@code 0} if it is not defined - */ - long getCurrentMetricValue(String metricName); - - /** - * @see #getCurrentMetricValue(String) - */ - long getCurrentMetricValue(String format, Object arg1); - - /** - * @see #getCurrentMetricValue(String) - */ - long getCurrentMetricValue(String format, Object arg1, Object arg2); - - /** - * @see #getCurrentMetricValue(String) - */ - long getCurrentMetricValue(String format, Object arg1, Object arg2, Object arg3); - - /** - * Gets the {@link ResolvedJavaMethod} associated with this {@linkplain DebugMethodMetrics}. - * - * @return the {@link ResolvedJavaMethod} of the current method metric - */ - ResolvedJavaMethod getMethod(); - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java new file mode 100644 index 00000000000..4e23426b18f --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; + +/** + * Options that configure a {@link DebugContext} and related functionality. + */ +public class DebugOptions { + static class DeprecatedOptionKey extends OptionKey { + private final OptionKey replacement; + + DeprecatedOptionKey(OptionKey replacement) { + super(replacement.getDefaultValue()); + this.replacement = replacement; + } + + @Override + protected void onValueUpdate(EconomicMap, Object> values, T oldValue, T newValue) { + // Ideally we'd use TTY here but it may not yet be initialized. + System.err.printf("Warning: the %s option is deprecated - use %s instead%n", getName(), replacement.getName()); + replacement.update(values, newValue); + } + } + + // @formatter:off + @Option(help = "Comma separated names of timers that are enabled irrespective of the value for Time option. " + + "An empty value enables all timers unconditionally.", type = OptionType.Debug) + public static final OptionKey Timers = new OptionKey<>(null); + @Option(help = "Comma separated names of counters that are enabled irrespective of the value for Count option. " + + "An empty value enables all counters unconditionally.", type = OptionType.Debug) + public static final OptionKey Counters = new OptionKey<>(null); + @Option(help = "Comma separated names of memory usage trackers that are enabled irrespective of the value for TrackMemUse option. " + + "An empty value enables all memory usage trackers unconditionally.", type = OptionType.Debug) + public static final OptionKey MemUseTrackers = new OptionKey<>(null); + + @Option(help = "Pattern for scope(s) in which counting is enabled (see DebugFilter and Debug.counter). " + + "An empty value enables all counters unconditionally.", type = OptionType.Debug) + public static final OptionKey Count = new OptionKey<>(null); + @Option(help = "Pattern for scope(s) in which memory use tracking is enabled (see DebugFilter and Debug.counter). " + + "An empty value enables all memory use trackers unconditionally.", type = OptionType.Debug) + public static final OptionKey TrackMemUse = new OptionKey<>(null); + @Option(help = "Pattern for scope(s) in which timing is enabled (see DebugFilter and Debug.timer). " + + "An empty value enables all timers unconditionally.", type = OptionType.Debug) + public static final OptionKey Time = new OptionKey<>(null); + + @Option(help = "Pattern for scope(s) in which verification is enabled (see DebugFilter and Debug.verify).", type = OptionType.Debug) + public static final OptionKey Verify = new OptionKey<>(null); + @Option(help = "Pattern for scope(s) in which dumping is enabled (see DebugFilter and Debug.dump)", type = OptionType.Debug) + public static final OptionKey Dump = new OptionKey<>(null); + @Option(help = "Pattern for scope(s) in which logging is enabled (see DebugFilter and Debug.log)", type = OptionType.Debug) + public static final OptionKey Log = new OptionKey<>(null); + + @Option(help = "Pattern for filtering debug scope output based on method context (see MethodFilter)", type = OptionType.Debug) + public static final OptionKey MethodFilter = new OptionKey<>(null); + @Option(help = "Only check MethodFilter against the root method in the context if true, otherwise check all methods", type = OptionType.Debug) + public static final OptionKey MethodFilterRootOnly = new OptionKey<>(false); + @Option(help = "Dump a before and after graph if the named phase changes the graph.%n" + + "The argument is substring matched against the simple name of the phase class", type = OptionType.Debug) + public static final OptionKey DumpOnPhaseChange = new OptionKey<>(null); + + @Option(help = "Listst the console at VM shutdown the metric names available to the Timers, Counters and MemUseTrackers option. " + + "Note that this only lists the metrics that were initialized during the VM execution and so " + + "will not include metrics for compiler code that is not executed.", type = OptionType.Debug) + public static final OptionKey ListMetrics = new OptionKey<>(false); + @Option(help = "File to which metrics are dumped per compilation. A CSV format is used if the file ends with .csv " + + "otherwise a more human readable format is used. The fields in the CSV format are: " + + "compilable, compilable_identity, compilation_nr, compilation_id, metric_name, metric_value", type = OptionType.Debug) + public static final OptionKey MetricsFile = new OptionKey<>(null); + @Option(help = "File to which aggregated metrics are dumped at shutdown. A CSV format is used if the file ends with .csv " + + "otherwise a more human readable format is used. If not specified, metrics are dumped to the console.", type = OptionType.Debug) + public static final OptionKey AggregatedMetricsFile = new OptionKey<>(null); + + @Option(help = "Only report metrics for threads whose name matches the regular expression.", type = OptionType.Debug) + public static final OptionKey MetricsThreadFilter = new OptionKey<>(null); + @Option(help = "Enable debug output for stub code generation and snippet preparation.", type = OptionType.Debug) + public static final OptionKey DebugStubsAndSnippets = new OptionKey<>(false); + @Option(help = "Send Graal compiler IR to dump handlers on error.", type = OptionType.Debug) + public static final OptionKey DumpOnError = new OptionKey<>(false); + @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug) + public static final OptionKey InterceptBailout = new OptionKey<>(false); + @Option(help = "Enable more verbose log output when available", type = OptionType.Debug) + public static final OptionKey LogVerbose = new OptionKey<>(false); + + @Option(help = "The directory where various Graal dump files are written.") + public static final OptionKey DumpPath = new OptionKey<>("dumps"); + @Option(help = "Print the name of each dump file path as it's created.") + public static final OptionKey ShowDumpFiles = new OptionKey<>(false); + + @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.", type = OptionType.Debug) + public static final OptionKey PrintCFG = new OptionKey<>(false); + @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug) + public static final OptionKey PrintBackendCFG = new OptionKey<>(true); + + @Option(help = "Output probabilities for fixed nodes during binary graph dumping.", type = OptionType.Debug) + public static final OptionKey PrintGraphProbabilities = new OptionKey<>(false); + @Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug) + public static final OptionKey PrintGraph = new OptionKey<>(true); + @Option(help = "Dump graphs in binary format instead of XML format.", type = OptionType.Debug) + public static final OptionKey PrintBinaryGraphs = new OptionKey<>(true); + @Option(help = "Print graphs to files instead of sending them over the network.", type = OptionType.Debug) + public static final OptionKey PrintGraphFile = new OptionKey<>(false); + + @Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug) + public static final OptionKey PrintGraphHost = new OptionKey<>("127.0.0.1"); + @Option(help = "Port part of the address to which graphs are dumped in XML format (ignored if PrintBinaryGraphs=true).", type = OptionType.Debug) + public static final OptionKey PrintXmlGraphPort = new OptionKey<>(4444); + @Option(help = "Port part of the address to which graphs are dumped in binary format (ignored if PrintBinaryGraphs=false).", type = OptionType.Debug) + public static final OptionKey PrintBinaryGraphPort = new OptionKey<>(4445); + @Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug) + public static final OptionKey PrintGraphWithSchedule = new OptionKey<>(false); + + @Option(help = "Enable dumping Truffle ASTs to the IdealGraphVisualizer.", type = OptionType.Debug) + public static final OptionKey PrintTruffleTrees = new OptionKey<>(true); + + @Option(help = "Treat any exceptions during dumping as fatal.", type = OptionType.Debug) + public static final OptionKey DumpingErrorsAreFatal = new OptionKey<>(false); + + @Option(help = "Enable dumping canonical text from for graphs.", type = OptionType.Debug) + public static final OptionKey PrintCanonicalGraphStrings = new OptionKey<>(false); + @Option(help = "Choose format used when dumping canonical text for graphs: " + + "0 gives a scheduled graph (better for spotting changes involving the schedule)" + + "while 1 gives a CFG containing expressions rooted at fixed nodes (better for spotting small structure differences)", type = OptionType.Debug) + public static final OptionKey PrintCanonicalGraphStringFlavor = new OptionKey<>(0); + @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) + public static final OptionKey CanonicalGraphStringsExcludeVirtuals = new OptionKey<>(true); + @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) + public static final OptionKey CanonicalGraphStringsCheckConstants = new OptionKey<>(false); + @Option(help = "Attempts to remove object identity hashes when dumping canonical text for graphs.", type = OptionType.Debug) + public static final OptionKey CanonicalGraphStringsRemoveIdentities = new OptionKey<>(true); + + @Option(help = "Clear the debug metrics after bootstrap.", type = OptionType.Debug) + public static final OptionKey ClearMetricsAfterBootstrap = new OptionKey<>(false); + @Option(help = "Do not compile anything on bootstrap but just initialize the compiler.", type = OptionType.Debug) + public static final OptionKey BootstrapInitializeOnly = new OptionKey<>(false); + + // These will be removed at some point + @Option(help = "Deprecated - use PrintGraphHost instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphAddress = new DebugOptions.DeprecatedOptionKey<>(PrintGraphHost); + @Option(help = "Deprecated - use PrintGraphWithSchedule instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphSchedule = new DebugOptions.DeprecatedOptionKey<>(PrintGraphWithSchedule); + @Option(help = "Deprecated - use PrintGraph instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraph = new DebugOptions.DeprecatedOptionKey<>(PrintGraph); + @Option(help = "Deprecated - use PrintGraphFile instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphFile = new DebugOptions.DeprecatedOptionKey<>(PrintGraphFile); + @Option(help = "Deprecated - use PrintXmlGraphPort instead.", type = OptionType.Debug) + static final OptionKey PrintIdealGraphPort = new DebugOptions.DeprecatedOptionKey<>(PrintXmlGraphPort); + // @formatter:on + + /** + * Gets the directory in which {@link DebugDumpHandler}s can generate output. This will be the + * directory specified by {@link #DumpPath} if it has been set otherwise it will be derived from + * the default value of {@link #DumpPath} and {@link PathUtilities#getGlobalTimeStamp()}. + * + * This method will ensure the returned directory exists, printing a message to {@link TTY} if + * it creates it. + * + * @return a path as described above whose directories are guaranteed to exist + * @throws IOException if there was an error in {@link Files#createDirectories} + */ + public static Path getDumpDirectory(OptionValues options) throws IOException { + Path dumpDir; + if (DumpPath.hasBeenSet(options)) { + dumpDir = Paths.get(DumpPath.getValue(options)); + } else { + dumpDir = Paths.get(DumpPath.getValue(options), String.valueOf(PathUtilities.getGlobalTimeStamp())); + } + dumpDir = dumpDir.toAbsolutePath(); + if (!Files.exists(dumpDir)) { + synchronized (DebugConfigImpl.class) { + if (!Files.exists(dumpDir)) { + Files.createDirectories(dumpDir); + TTY.println("Dumping debug output in %s", dumpDir.toString()); + } + } + } + return dumpDir; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValueMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugValueMap.java similarity index 89% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValueMap.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugValueMap.java index 7b8753a9e01..08b72bd0245 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValueMap.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugValueMap.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.debug.internal; +package org.graalvm.compiler.debug; import java.util.ArrayList; import java.util.Arrays; @@ -30,10 +30,13 @@ import java.util.List; import java.util.Map; /** - * A node in a tree of {@link DebugValue}s. + * A node in a tree of values. */ public class DebugValueMap { + /** + * The top level maps for all threads. + */ private static final List topLevelMaps = new ArrayList<>(); private long[] values; @@ -120,6 +123,21 @@ public class DebugValueMap { return topLevelMaps; } + /** + * The top level map for the current thread. + */ + private static final ThreadLocal topLevelMap = new ThreadLocal<>(); + + static DebugValueMap getTopLevelMap() { + DebugValueMap map = topLevelMap.get(); + if (map == null) { + map = new DebugValueMap(Thread.currentThread().getName()); + topLevelMap.set(map); + registerTopLevel(map); + } + return map; + } + public void normalize() { if (hasChildren()) { Map occurred = new HashMap<>(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugVerifyHandler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugVerifyHandler.java index d949f97bd06..736da23e00e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugVerifyHandler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugVerifyHandler.java @@ -25,13 +25,16 @@ package org.graalvm.compiler.debug; /** * Performs some kind of verification on an object. */ -public interface DebugVerifyHandler { +public interface DebugVerifyHandler extends DebugHandler { /** * Verifies that a given object satisfies some invariants. * * @param object object to verify - * @param message description of verification context + * @param debug the debug context requesting the dump + * @param format a format string specifying a title that describes the context of the + * verification (e.g., the compiler phase in which request is made) + * @param arguments arguments referenced by the format specifiers in {@code format} */ - void verify(Object object, String message); + void verify(DebugContext debug, Object object, String format, Object... arguments); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DelegatingDebugConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DelegatingDebugConfig.java deleted file mode 100644 index ac336ae9ba7..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DelegatingDebugConfig.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug; - -import java.io.PrintStream; -import java.util.Collection; -import java.util.EnumMap; -import java.util.Map; - -import org.graalvm.compiler.debug.internal.DebugScope; - -public class DelegatingDebugConfig implements DebugConfig { - - protected final DebugConfig delegate; - - /** - * The features of a {@link DelegatingDebugConfig} that can be force - * {@linkplain DelegatingDebugConfig#enable(Feature) enabled}/ - * {@linkplain DelegatingDebugConfig#disable(Feature) disabled} or - * {@linkplain DelegatingDebugConfig#delegate(Feature) delegated}. - */ - public enum Feature { - /** - * @see Debug#isLogEnabledForMethod() - */ - LOG_METHOD, - /** - * @see Debug#isDumpEnabledForMethod() - */ - DUMP_METHOD, - /** - * @see Debug#isVerifyEnabled() - */ - VERIFY, - /** - * @see Debug#isVerifyEnabledForMethod() - */ - VERIFY_METHOD, - /** - * @see Debug#isCountEnabled() - */ - COUNT, - /** - * @see Debug#isMethodMeterEnabled() - */ - METHOD_METRICS, - /** - * @see Debug#isMemUseTrackingEnabled() - */ - TRACK_MEM_USE, - /** - * @see Debug#isTimeEnabled() - */ - TIME, - /** - * @see DebugConfig#interceptException(Throwable) - */ - INTERCEPT - } - - private final Map featureState = new EnumMap<>(Feature.class); - - /** - * The debug levels of a {@link DelegatingDebugConfig} than can be - * {@linkplain DelegatingDebugConfig#override(Level, int) overridden} or - * {@linkplain DelegatingDebugConfig#delegate(Level) delegated}. - */ - public enum Level { - LOG, - DUMP - } - - private final Map levelState = new EnumMap<>(Level.class); - - /** - * Creates a config that delegates to the {@link DebugScope#getConfig() current config}. - */ - public DelegatingDebugConfig() { - this(DebugScope.getConfig()); - } - - /** - * Creates a config that delegates to a given config. - */ - public DelegatingDebugConfig(DebugConfig delegate) { - this.delegate = delegate; - } - - public DelegatingDebugConfig enable(Feature feature) { - featureState.put(feature, Boolean.TRUE); - return this; - } - - public DelegatingDebugConfig disable(Feature feature) { - featureState.put(feature, Boolean.FALSE); - return this; - } - - public DelegatingDebugConfig override(Level level, int newLevel) { - levelState.put(level, newLevel); - return this; - } - - public DelegatingDebugConfig delegate(Feature feature) { - featureState.put(feature, null); - return this; - } - - public DelegatingDebugConfig delegate(Level level) { - levelState.put(level, null); - return this; - } - - @Override - public int getLogLevel() { - Integer ls = levelState.get(Level.LOG); - if (ls == null) { - return delegate.getLogLevel(); - } - return ls.intValue(); - } - - @Override - public boolean isLogEnabledForMethod() { - Boolean fs = featureState.get(Feature.LOG_METHOD); - if (fs == null) { - return delegate.isLogEnabledForMethod(); - } - return fs.booleanValue(); - } - - @Override - public boolean isCountEnabled() { - Boolean fs = featureState.get(Feature.COUNT); - if (fs == null) { - return delegate.isCountEnabled(); - } - return fs.booleanValue(); - } - - @Override - public boolean isMemUseTrackingEnabled() { - Boolean fs = featureState.get(Feature.TRACK_MEM_USE); - if (fs == null) { - return delegate.isMemUseTrackingEnabled(); - } - return fs.booleanValue(); - } - - @Override - public int getDumpLevel() { - Integer ls = levelState.get(Level.DUMP); - if (ls == null) { - return delegate.getDumpLevel(); - } - return ls.intValue(); - } - - @Override - public boolean isDumpEnabledForMethod() { - Boolean fs = featureState.get(Feature.DUMP_METHOD); - if (fs == null) { - return delegate.isDumpEnabledForMethod(); - } - return fs.booleanValue(); - } - - @Override - public boolean isVerifyEnabled() { - Boolean fs = featureState.get(Feature.VERIFY); - if (fs == null) { - return delegate.isVerifyEnabled(); - } - return fs.booleanValue(); - } - - @Override - public boolean isVerifyEnabledForMethod() { - Boolean fs = featureState.get(Feature.VERIFY_METHOD); - if (fs == null) { - return delegate.isVerifyEnabledForMethod(); - } - return fs.booleanValue(); - } - - @Override - public boolean isTimeEnabled() { - Boolean fs = featureState.get(Feature.TIME); - if (fs == null) { - return delegate.isTimeEnabled(); - } - return fs.booleanValue(); - } - - @Override - public boolean isMethodMeterEnabled() { - Boolean fs = featureState.get(Feature.METHOD_METRICS); - if (fs == null) { - return delegate.isMethodMeterEnabled(); - } - return fs.booleanValue(); - } - - @Override - public RuntimeException interceptException(Throwable e) { - Boolean fs = featureState.get(Feature.INTERCEPT); - if (fs == null || fs) { - return delegate.interceptException(e); - } - return null; - } - - @Override - public Collection dumpHandlers() { - return delegate.dumpHandlers(); - } - - @Override - public Collection verifyHandlers() { - return delegate.verifyHandlers(); - } - - @Override - public PrintStream output() { - return delegate.output(); - } - - @Override - public void addToContext(Object o) { - delegate.addToContext(o); - } - - @Override - public void removeFromContext(Object o) { - delegate.removeFromContext(o); - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DiagnosticsOutputDirectory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DiagnosticsOutputDirectory.java new file mode 100644 index 00000000000..377ba003579 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DiagnosticsOutputDirectory.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.zip.Deflater; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import org.graalvm.compiler.options.OptionValues; + +/** + * Manages a directory into which diagnostics such crash reports and dumps should be written. The + * directory is archived and deleted when {@link #close()} is called. + */ +public class DiagnosticsOutputDirectory { + + /** + * Use an illegal file name to denote that {@link #close()} has been called. + */ + private static final String CLOSED = "\u0000"; + + public DiagnosticsOutputDirectory(OptionValues options) { + this.options = options; + } + + private final OptionValues options; + + private String path; + + /** + * Gets the path to the output directory managed by this object, creating if it doesn't exist + * and has not been deleted. + * + * @returns the directory or {@code null} if the could not be created or has been deleted + */ + public String getPath() { + return getPath(true); + } + + /** + * Gets a unique identifier for this execution such as a process ID. + */ + protected String getExecutionID() { + try { + String runtimeName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName(); + try { + int index = runtimeName.indexOf('@'); + if (index != -1) { + long pid = Long.parseLong(runtimeName.substring(0, index)); + return Long.toString(pid); + } + } catch (NumberFormatException e) { + } + return runtimeName; + } catch (LinkageError err) { + return String.valueOf(org.graalvm.compiler.debug.PathUtilities.getGlobalTimeStamp()); + } + } + + private synchronized String getPath(boolean createIfNull) { + if (path == null && createIfNull) { + path = createPath(); + File dir = new File(path).getAbsoluteFile(); + if (!dir.exists()) { + dir.mkdirs(); + if (!dir.exists()) { + TTY.println("Warning: could not create Graal diagnostic directory " + dir); + return null; + } + } + } + return CLOSED.equals(path) ? null : path; + } + + /** + * Gets the path of the directory to be created. + * + * Subclasses can override this to determine how the path name is created. + * + * @return the path to be created + */ + protected String createPath() { + Path baseDir; + try { + baseDir = DebugOptions.getDumpDirectory(options); + } catch (IOException e) { + // Default to current directory if there was a problem creating the + // directory specified by the DumpPath option. + baseDir = Paths.get("."); + } + return baseDir.resolve("graal_diagnostics_" + getExecutionID()).toAbsolutePath().toString(); + } + + /** + * Archives and deletes this directory if it exists. + */ + public void close() { + archiveAndDelete(); + } + + /** + * Archives and deletes the {@linkplain #getPath() output directory} if it exists. + */ + private synchronized void archiveAndDelete() { + String outDir = getPath(false); + if (outDir != null) { + // Notify other threads calling getPath() that the directory is deleted. + // This attempts to mitigate other threads writing to the directory + // while it is being archived and deleted. + path = CLOSED; + + Path dir = Paths.get(outDir); + if (dir.toFile().exists()) { + File zip = new File(outDir + ".zip").getAbsoluteFile(); + List toDelete = new ArrayList<>(); + try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip))) { + zos.setLevel(Deflater.BEST_COMPRESSION); + Files.walkFileTree(dir, Collections.emptySet(), Integer.MAX_VALUE, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + if (attrs.isRegularFile()) { + String name = dir.relativize(file).toString(); + ZipEntry ze = new ZipEntry(name); + zos.putNextEntry(ze); + zos.write(Files.readAllBytes(file)); + zos.closeEntry(); + } + toDelete.add(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path d, IOException exc) throws IOException { + toDelete.add(d); + return FileVisitResult.CONTINUE; + } + }); + // Keep this in sync with the catch_files in common.hocon + TTY.println("Graal diagnostic output saved in %s", zip); + } catch (IOException e) { + TTY.printf("IO error archiving %s:%n%s. The directory will not be deleted and must be " + + "manually removed once the VM exits.%n", dir, e); + toDelete.clear(); + } + if (!toDelete.isEmpty()) { + IOException lastDeletionError = null; + for (Path p : toDelete) { + try { + Files.delete(p); + } catch (IOException e) { + lastDeletionError = e; + } + } + if (lastDeletionError != null) { + TTY.printf("IO error deleting %s:%n%s. This is most likely due to a compilation on " + + "another thread holding a handle to a file within this directory. " + + "Please delete the directory manually once the VM exits.%n", dir, lastDeletionError); + } + } + } + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Fingerprint.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Fingerprint.java deleted file mode 100644 index 367d0ddfb04..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Fingerprint.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionValue; - -/** - * Facility for fingerprinting execution. - */ -public class Fingerprint implements AutoCloseable { - - public static class Options { - @Option(help = "Enables execution fingerprinting.")// - public static final OptionValue UseFingerprinting = new OptionValue<>(false); - - @Option(help = "Limit number of events shown in fingerprinting error message.")// - public static final OptionValue FingerprintErrorEventTailLength = new OptionValue<>(50); - - @Option(help = "Fingerprinting event at which to execute breakpointable code.")// - public static final OptionValue FingerprintingBreakpointEvent = new OptionValue<>(-1); - } - - /** - * Determines whether fingerprinting is enabled. - */ - public static final boolean ENABLED = Options.UseFingerprinting.getValue(); - - private static final ThreadLocal current = ENABLED ? new ThreadLocal<>() : null; - - private final List events; - private int index; - - /** - * Creates an object to record a fingerprint. - */ - public Fingerprint() { - events = new ArrayList<>(); - index = -1; - } - - /** - * Creates an object to verify execution matches a given fingerprint. - * - * @param toVerifyAgainst the fingerprint events to verify against - */ - public Fingerprint(List toVerifyAgainst) { - this.events = toVerifyAgainst; - index = 0; - } - - /** - * Creates an object to verify execution matches a given fingerprint. - * - * @param toVerifyAgainst the fingerprint to verify against - */ - public Fingerprint(Fingerprint toVerifyAgainst) { - this(toVerifyAgainst.events); - } - - public Collection getEvents() { - return Collections.unmodifiableCollection(events); - } - - /** - * Starts fingerprint recording or verification for the current thread. At most one fingerprint - * object can be active for any thread. - */ - public Fingerprint open() { - if (ENABLED) { - assert current.get() == null; - current.set(this); - return this; - } - return null; - } - - /** - * Finishes fingerprint recording or verification for the current thread. - */ - @Override - public void close() { - if (ENABLED) { - assert current.get() == this; - current.set(null); - } - } - - private static final int BREAKPOINT_EVENT = Options.FingerprintingBreakpointEvent.getValue(); - - /** - * Submits an execution event for the purpose of recording or verifying a fingerprint. This must - * only be called if {@link #ENABLED} is {@code true}. - */ - public static void submit(String format, Object... args) { - assert ENABLED : "fingerprinting must be enabled (-Dgraal." + Options.UseFingerprinting.getName() + "=true)"; - Fingerprint fingerprint = current.get(); - if (fingerprint != null) { - int eventId = fingerprint.nextEventId(); - if (eventId == BREAKPOINT_EVENT) { - // Set IDE breakpoint on the following line and set the relevant - // system property to debug a fingerprint verification error. - System.console(); - } - fingerprint.event(String.format(eventId + ": " + format, args)); - } - } - - private int nextEventId() { - return index == -1 ? events.size() : index; - } - - private static final int MAX_EVENT_TAIL_IN_ERROR_MESSAGE = Options.FingerprintErrorEventTailLength.getValue(); - - private String tail() { - int start = Math.max(index - MAX_EVENT_TAIL_IN_ERROR_MESSAGE, 0); - return events.subList(start, index).stream().collect(Collectors.joining(String.format("%n"))); - } - - private void event(String entry) { - if (index == -1) { - events.add(entry); - } else { - if (index > events.size()) { - throw new InternalError(String.format("%s%nOriginal fingerprint limit reached", tail())); - } - String l = events.get(index); - if (!l.equals(entry)) { - throw new InternalError(String.format("%s%nFingerprint differs at event %d%nexpected: %s%n actual: %s", tail(), index, l, entry)); - } - index++; - } - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GlobalMetrics.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GlobalMetrics.java new file mode 100644 index 00000000000..4e7b22d38eb --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GlobalMetrics.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import java.io.IOException; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Collections; +import java.util.List; + +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.MapCursor; +import org.graalvm.util.Pair; + +/** + * Metric values that can be {@linkplain #add(DebugContext) updated} by multiple threads. + */ +public class GlobalMetrics { + long[] values; + + /** + * Adds the values in {@code debug} to the values in this object. + */ + public synchronized void add(DebugContext debug) { + values = debug.addValuesTo(values); + } + + /** + * Clears all values in this object. + */ + public void clear() { + values = null; + } + + /** + * Creates and returns a sorted map from metric names to their values in this object. + */ + public EconomicMap asKeyValueMap() { + List keys = KeyRegistry.getKeys(); + Collections.sort(keys, MetricKey.NAME_COMPARATOR); + EconomicMap res = EconomicMap.create(keys.size()); + long[] vals = values; + for (MetricKey key : keys) { + int index = ((AbstractKey) key).getIndex(); + if (vals == null || index >= vals.length) { + res.put(key, 0L); + } else { + res.put(key, vals[index]); + } + } + return res; + } + + /** + * Prints the values in the object to the file specified by + * {@link DebugOptions#AggregatedMetricsFile} if present otherwise to + * {@link DebugContext#DEFAULT_LOG_STREAM}. + */ + public void print(OptionValues options) { + long[] vals = values; + if (vals != null) { + EconomicMap map = asKeyValueMap(); + String metricsFile = DebugOptions.AggregatedMetricsFile.getValue(options); + boolean csv = metricsFile != null && (metricsFile.endsWith(".csv") || metricsFile.endsWith(".CSV")); + try (PrintStream p = metricsFile == null ? DebugContext.DEFAULT_LOG_STREAM : new PrintStream(Files.newOutputStream(Paths.get(metricsFile)))) { + if (!csv) { + if (!map.isEmpty()) { + p.println("++ Aggregated Metrics ++"); + } + } + String csvFormat = CSVUtil.buildFormatString("%s", "%s", "%s"); + MapCursor e = map.getEntries(); + while (e.advance()) { + MetricKey key = e.getKey(); + if (csv) { + Pair valueAndUnit = key.toCSVFormat(e.getValue()); + CSVUtil.Escape.println(p, csvFormat, key.getName(), valueAndUnit.getLeft(), valueAndUnit.getRight()); + } else { + p.println(key.getName() + "=" + key.toHumanReadableFormat(e.getValue())); + } + } + if (!csv) { + if (!map.isEmpty()) { + p.println("-- Aggregated Metrics --"); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + if (DebugOptions.ListMetrics.getValue(options)) { + PrintStream p = System.out; + p.println("++ Metric Keys ++"); + List keys = KeyRegistry.getKeys(); + Collections.sort(keys, MetricKey.NAME_COMPARATOR); + for (MetricKey key : keys) { + String name = key.getDocName(); + if (name != null) { + String doc = key.getDoc(); + if (doc != null) { + p.println(name + ": " + doc); + } else { + p.println(name); + } + } + } + p.println("-- Metric Keys --"); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java deleted file mode 100644 index 69c6e466aab..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalDebugConfig.java +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug; - -import java.io.PrintStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; - -import jdk.vm.ci.code.BailoutException; -import jdk.vm.ci.meta.JavaMethod; - -public class GraalDebugConfig implements DebugConfig { - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; - return assertionsEnabled; - } - - public static class Options { - // @formatter:off - @Option(help = "Pattern for scope(s) in which dumping is enabled (see DebugFilter and Debug.dump)", type = OptionType.Debug) - public static final OptionValue Dump = new OptionValue<>(null); - @Option(help = "Pattern for scope(s) in which counting is enabled (see DebugFilter and Debug.counter). " + - "An empty value enables all counters unconditionally.", type = OptionType.Debug) - public static final OptionValue Count = new OptionValue<>(null); - @Option(help = "Pattern for scope(s) in which verification is enabled (see DebugFilter and Debug.verify).", type = OptionType.Debug) - public static final OptionValue Verify = new OptionValue() { - @Override - protected String defaultValue() { - return assertionsEnabled() ? "" : null; - } - }; - @Option(help = "Pattern for scope(s) in which memory use tracking is enabled (see DebugFilter and Debug.counter). " + - "An empty value enables all memory use trackers unconditionally.", type = OptionType.Debug) - public static final OptionValue TrackMemUse = new OptionValue<>(null); - @Option(help = "Pattern for scope(s) in which timing is enabled (see DebugFilter and Debug.timer). " + - "An empty value enables all timers unconditionally.", type = OptionType.Debug) - public static final OptionValue Time = new OptionValue<>(null); - @Option(help = "Pattern for scope(s) in which logging is enabled (see DebugFilter and Debug.log)", type = OptionType.Debug) - public static final OptionValue Log = new OptionValue<>(null); - @Option(help = "Pattern for filtering debug scope output based on method context (see MethodFilter)", type = OptionType.Debug) - public static final OptionValue MethodFilter = new OptionValue<>(null); - @Option(help = "Only check MethodFilter against the root method in the context if true, otherwise check all methods", type = OptionType.Debug) - public static final OptionValue MethodFilterRootOnly = new OptionValue<>(false); - - @Option(help = "How to print counters and timing values:%n" + - "Name - aggregate by unqualified name%n" + - "Partial - aggregate by partially qualified name (e.g., A.B.C.D.Counter and X.Y.Z.D.Counter will be merged to D.Counter)%n" + - "Complete - aggregate by qualified name%n" + - "Thread - aggregate by qualified name and thread", type = OptionType.Debug) - public static final OptionValue DebugValueSummary = new OptionValue<>("Name"); - @Option(help = "Print counters and timers in a human readable form.", type = OptionType.Debug) - public static final OptionValue DebugValueHumanReadable = new OptionValue<>(true); - @Option(help = "Omit reporting 0-value counters", type = OptionType.Debug) - public static final OptionValue SuppressZeroDebugValues = new OptionValue<>(true); - @Option(help = "Only report debug values for maps which match the regular expression.", type = OptionType.Debug) - public static final OptionValue DebugValueThreadFilter = new OptionValue<>(null); - @Option(help = "Write debug values into a file instead of the terminal. " + - "If DebugValueSummary is Thread, the thread name will be prepended.", type = OptionType.Debug) - public static final OptionValue DebugValueFile = new OptionValue<>(null); - @Option(help = "Send Graal compiler IR to dump handlers on error", type = OptionType.Debug) - public static final OptionValue DumpOnError = new OptionValue<>(false); - @Option(help = "Intercept also bailout exceptions", type = OptionType.Debug) - public static final OptionValue InterceptBailout = new OptionValue<>(false); - @Option(help = "Enable more verbose log output when available", type = OptionType.Debug) - public static final OptionValue LogVerbose = new OptionValue<>(false); - - @Option(help = "The directory where various Graal dump files are written.") - public static final OptionValue DumpPath = new OptionValue<>("."); - - @Option(help = "Enable dumping to the C1Visualizer. Enabling this option implies PrintBackendCFG.", type = OptionType.Debug) - public static final OptionValue PrintCFG = new OptionValue<>(false); - @Option(help = "Enable dumping LIR, register allocation and code generation info to the C1Visualizer.", type = OptionType.Debug) - public static final OptionValue PrintBackendCFG = new OptionValue<>(true); - @Option(help = "Base filename when dumping C1Visualizer output to files.", type = OptionType.Debug) - public static final OptionValue PrintCFGFileName = new OptionValue<>("compilations"); - - @Option(help = "Output probabilities for fixed nodes during binary graph dumping", type = OptionType.Debug) - public static final OptionValue PrintGraphProbabilities = new OptionValue<>(false); - @Option(help = "Enable dumping to the IdealGraphVisualizer.", type = OptionType.Debug) - public static final OptionValue PrintIdealGraph = new OptionValue<>(true); - @Option(help = "Dump IdealGraphVisualizer output in binary format", type = OptionType.Debug) - public static final OptionValue PrintBinaryGraphs = new OptionValue<>(true); - @Option(help = "Print Ideal graphs as opposed to sending them over the network.", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphFile = new OptionValue<>(false); - @Option(help = "Base filename when dumping Ideal graphs to files.", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphFileName = new OptionValue<>("runtime-graphs"); - - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphAddress = new OptionValue<>("127.0.0.1"); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphPort = new OptionValue<>(4444); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintBinaryGraphPort = new OptionValue<>(4445); - @Option(help = "", type = OptionType.Debug) - public static final OptionValue PrintIdealGraphSchedule = new OptionValue<>(false); - @Option(help = "Enable dumping Truffle ASTs to the IdealGraphVisualizer.", type = OptionType.Debug) - public static final OptionValue PrintTruffleTrees = new OptionValue<>(true); - - @Option(help = "Enable dumping canonical text from for graphs.", type = OptionType.Debug) - public static final OptionValue PrintCanonicalGraphStrings = new OptionValue<>(false); - @Option(help = "Base directory when dumping graphs strings to files.", type = OptionType.Debug) - public static final OptionValue PrintCanonicalGraphStringsDirectory = new OptionValue<>("graph-strings"); - @Option(help = "Choose format used when dumping canonical text for graphs: " + - "0 gives a scheduled graph (better for spotting changes involving the schedule)" + - "while 1 gives a CFG containing expressions rooted at fixed nodes (better for spotting small structure differences)", type = OptionType.Debug) - public static final OptionValue PrintCanonicalGraphStringFlavor = new OptionValue<>(0); - @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionValue CanonicalGraphStringsExcludeVirtuals = new OptionValue<>(true); - @Option(help = "Exclude virtual nodes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionValue CanonicalGraphStringsCheckConstants = new OptionValue<>(false); - @Option(help = "Attempts to remove object identity hashes when dumping canonical text for graphs.", type = OptionType.Debug) - public static final OptionValue CanonicalGraphStringsRemoveIdentities = new OptionValue<>(true); - - @Option(help = "Enable per method metrics that are collected across all compilations of a method." + - "Pattern for scope(s) in which method metering is enabled (see DebugFilter and Debug.metric).", type = OptionType.Debug) - public static final OptionValue MethodMeter = new OptionValue<>(null); - @Option(help = "If a global metric (DebugTimer, DebugCounter or DebugMemUseTracker) is enabled in the same scope as a method metric, " + - "use the global metric to update the method metric for the current compilation. " + - "This option enables the re-use of global metrics on per-compilation basis. " + - "Whenever a value is added to a global metric, the value is also added to a MethodMetric under the same name " + - "as the global metric. " + - "This option incurs a small but constant overhead due to the context method lookup at each metric update. " + - "Format to specify GlobalMetric interception:(Timers|Counters|MemUseTrackers)(,Timers|,Counters|,MemUseTrackers)*", type = OptionType.Debug) - public static final OptionValue GlobalMetricsInterceptedByMethodMetrics = new OptionValue<>(null); - @Option(help = "Force-enable debug code paths", type = OptionType.Debug) - public static final OptionValue ForceDebugEnable = new OptionValue<>(false); - @Option(help = "Clear the debug metrics after bootstrap.", type = OptionType.Debug) - public static final OptionValue ClearMetricsAfterBootstrap = new OptionValue<>(false); - @Option(help = "Do not compile anything on bootstrap but just initialize the compiler.", type = OptionType.Debug) - public static final OptionValue BootstrapInitializeOnly = new OptionValue<>(false); - // @formatter:on - } - - public static boolean isNotEmpty(OptionValue option) { - return option.getValue() != null && !option.getValue().isEmpty(); - } - - public static boolean areDebugScopePatternsEnabled() { - return Options.DumpOnError.getValue() || Options.Dump.getValue() != null || Options.Log.getValue() != null || areScopedGlobalMetricsEnabled(); - } - - public static boolean isGlobalMetricsInterceptedByMethodMetricsEnabled() { - return isNotEmpty(Options.GlobalMetricsInterceptedByMethodMetrics); - } - - /** - * Determines if any of {@link Options#Count}, {@link Options#Time} or - * {@link Options#TrackMemUse} has a non-null, non-empty value. - */ - public static boolean areScopedGlobalMetricsEnabled() { - return isNotEmpty(Options.Count) || isNotEmpty(Options.Time) || isNotEmpty(Options.TrackMemUse) || isNotEmpty(Options.MethodMeter); - } - - private final DebugFilter countFilter; - private final DebugFilter logFilter; - private final DebugFilter methodMetricsFilter; - private final DebugFilter trackMemUseFilter; - private final DebugFilter timerFilter; - private final DebugFilter dumpFilter; - private final DebugFilter verifyFilter; - private final MethodFilter[] methodFilter; - private final List dumpHandlers; - private final List verifyHandlers; - private final PrintStream output; - - // Use an identity set to handle context objects that don't support hashCode(). - private final Set extraFilters = Collections.newSetFromMap(new IdentityHashMap<>()); - - public GraalDebugConfig(String logFilter, String countFilter, String trackMemUseFilter, String timerFilter, String dumpFilter, String verifyFilter, String methodFilter, - String methodMetricsFilter, PrintStream output, List dumpHandlers, List verifyHandlers) { - this.logFilter = DebugFilter.parse(logFilter); - this.countFilter = DebugFilter.parse(countFilter); - this.trackMemUseFilter = DebugFilter.parse(trackMemUseFilter); - this.timerFilter = DebugFilter.parse(timerFilter); - this.dumpFilter = DebugFilter.parse(dumpFilter); - this.verifyFilter = DebugFilter.parse(verifyFilter); - this.methodMetricsFilter = DebugFilter.parse(methodMetricsFilter); - if (methodFilter == null || methodFilter.isEmpty()) { - this.methodFilter = null; - } else { - this.methodFilter = org.graalvm.compiler.debug.MethodFilter.parse(methodFilter); - } - - // Report the filters that have been configured so the user can verify it's what they expect - if (logFilter != null || countFilter != null || timerFilter != null || dumpFilter != null || methodFilter != null) { - // TTY.println(Thread.currentThread().getName() + ": " + toString()); - } - this.dumpHandlers = dumpHandlers; - this.verifyHandlers = verifyHandlers; - this.output = output; - } - - @Override - public int getLogLevel() { - return getLevel(logFilter); - } - - @Override - public boolean isLogEnabledForMethod() { - return isEnabledForMethod(logFilter); - } - - @Override - public boolean isCountEnabled() { - return isEnabled(countFilter); - } - - @Override - public boolean isMemUseTrackingEnabled() { - return isEnabled(trackMemUseFilter); - } - - @Override - public int getDumpLevel() { - return getLevel(dumpFilter); - } - - @Override - public boolean isDumpEnabledForMethod() { - return isEnabledForMethod(dumpFilter); - } - - @Override - public boolean isVerifyEnabled() { - return isEnabled(verifyFilter); - } - - @Override - public boolean isVerifyEnabledForMethod() { - return isEnabledForMethod(verifyFilter); - } - - @Override - public boolean isMethodMeterEnabled() { - return isEnabled(methodMetricsFilter); - } - - @Override - public boolean isTimeEnabled() { - return isEnabled(timerFilter); - } - - @Override - public PrintStream output() { - return output; - } - - private boolean isEnabled(DebugFilter filter) { - return getLevel(filter) > 0; - } - - private int getLevel(DebugFilter filter) { - int level; - if (filter == null) { - level = 0; - } else { - level = filter.matchLevel(Debug.currentScope()); - } - if (level > 0 && !checkMethodFilter()) { - level = 0; - } - return level; - } - - private boolean isEnabledForMethod(DebugFilter filter) { - return filter != null && checkMethodFilter(); - } - - /** - * Extracts a {@link JavaMethod} from an opaque debug context. - * - * @return the {@link JavaMethod} represented by {@code context} or null - */ - public static JavaMethod asJavaMethod(Object context) { - if (context instanceof JavaMethodContext) { - return ((JavaMethodContext) context).asJavaMethod(); - } - if (context instanceof JavaMethod) { - return (JavaMethod) context; - } - return null; - } - - private boolean checkMethodFilter() { - if (methodFilter == null && extraFilters.isEmpty()) { - return true; - } else { - JavaMethod lastMethod = null; - for (Object o : Debug.context()) { - if (extraFilters.contains(o)) { - return true; - } else if (methodFilter != null) { - JavaMethod method = asJavaMethod(o); - if (method != null) { - if (!Options.MethodFilterRootOnly.getValue()) { - if (org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, method)) { - return true; - } - } else { - /* - * The context values operate as a stack so if we want MethodFilter to - * only apply to the root method we have to check only the last method - * seen. - */ - lastMethod = method; - } - } - } - } - if (lastMethod != null && org.graalvm.compiler.debug.MethodFilter.matches(methodFilter, lastMethod)) { - return true; - } - return false; - } - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("Debug config:"); - add(sb, "Log", logFilter); - add(sb, "Count", countFilter); - add(sb, "MethodMeter", methodMetricsFilter); - add(sb, "Time", timerFilter); - add(sb, "Dump", dumpFilter); - add(sb, "MethodFilter", methodFilter); - return sb.toString(); - } - - private static void add(StringBuilder sb, String name, Object filter) { - if (filter != null) { - sb.append(' '); - sb.append(name); - sb.append('='); - if (filter instanceof Object[]) { - sb.append(Arrays.toString((Object[]) filter)); - } else { - sb.append(String.valueOf(filter)); - } - } - } - - @Override - public RuntimeException interceptException(Throwable e) { - if (e instanceof BailoutException && !Options.InterceptBailout.getValue()) { - return null; - } - Debug.setConfig(Debug.fixedConfig(Debug.BASIC_LOG_LEVEL, Debug.BASIC_LOG_LEVEL, false, false, false, false, false, dumpHandlers, verifyHandlers, output)); - Debug.log("Exception occurred in scope: %s", Debug.currentScope()); - Map firstSeen = new IdentityHashMap<>(); - for (Object o : Debug.context()) { - // Only dump a context object once. - if (!firstSeen.containsKey(o)) { - firstSeen.put(o, o); - if (Options.DumpOnError.getValue()) { - Debug.dump(Debug.BASIC_LOG_LEVEL, o, "Exception: %s", e); - } else { - Debug.log("Context obj %s", o); - } - } - } - return null; - } - - @Override - public Collection dumpHandlers() { - return dumpHandlers; - } - - @Override - public Collection verifyHandlers() { - return verifyHandlers; - } - - @Override - public void addToContext(Object o) { - extraFilters.add(o); - } - - @Override - public void removeFromContext(Object o) { - extraFilters.remove(o); - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalError.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalError.java index 4ff6cc51ffa..cc0737e2180 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalError.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalError.java @@ -53,6 +53,21 @@ public class GraalError extends Error { throw new GraalError(cause); } + /** + * Checks a given condition and throws a {@link GraalError} if it is false. Guarantees are + * stronger than assertions in that they are always checked. Error messages for guarantee + * violations should clearly indicate the nature of the problem as well as a suggested solution + * if possible. + * + * @param condition the condition to check + * @param msg the message that will be associated with the error + */ + public static void guarantee(boolean condition, String msg) { + if (!condition) { + throw new GraalError("failed guarantee: " + msg); + } + } + /** * Checks a given condition and throws a {@link GraalError} if it is false. Guarantees are * stronger than assertions in that they are always checked. Error messages for guarantee @@ -62,8 +77,58 @@ public class GraalError extends Error { * @param condition the condition to check * @param msg the message that will be associated with the error, in * {@link String#format(String, Object...)} syntax - * @param args arguments to the format string + * @param arg argument to the format string in {@code msg} */ + public static void guarantee(boolean condition, String msg, Object arg) { + if (!condition) { + throw new GraalError("failed guarantee: " + msg, arg); + } + } + + /** + * Checks a given condition and throws a {@link GraalError} if it is false. Guarantees are + * stronger than assertions in that they are always checked. Error messages for guarantee + * violations should clearly indicate the nature of the problem as well as a suggested solution + * if possible. + * + * @param condition the condition to check + * @param msg the message that will be associated with the error, in + * {@link String#format(String, Object...)} syntax + * @param arg1 argument to the format string in {@code msg} + * @param arg2 argument to the format string in {@code msg} + */ + public static void guarantee(boolean condition, String msg, Object arg1, Object arg2) { + if (!condition) { + throw new GraalError("failed guarantee: " + msg, arg1, arg2); + } + } + + /** + * Checks a given condition and throws a {@link GraalError} if it is false. Guarantees are + * stronger than assertions in that they are always checked. Error messages for guarantee + * violations should clearly indicate the nature of the problem as well as a suggested solution + * if possible. + * + * @param condition the condition to check + * @param msg the message that will be associated with the error, in + * {@link String#format(String, Object...)} syntax + * @param arg1 argument to the format string in {@code msg} + * @param arg2 argument to the format string in {@code msg} + * @param arg3 argument to the format string in {@code msg} + */ + public static void guarantee(boolean condition, String msg, Object arg1, Object arg2, Object arg3) { + if (!condition) { + throw new GraalError("failed guarantee: " + msg, arg1, arg2, arg3); + } + } + + /** + * This override exists to catch cases when {@link #guarantee(boolean, String, Object)} is + * called with one argument bound to a varargs method parameter. It will bind to this method + * instead of the single arg variant and produce a deprecation warning instead of silently + * wrapping the Object[] inside of another Object[]. + */ + @Deprecated public static void guarantee(boolean condition, String msg, Object... args) { if (!condition) { throw new GraalError("failed guarantee: " + msg, args); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Indent.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Indent.java index ecb6cb3ac7a..d9f583fb3cd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Indent.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Indent.java @@ -23,7 +23,7 @@ package org.graalvm.compiler.debug; /** - * Object used to close a debug {@link Debug#indent() indentation} scope. + * Object used to close a debug {@link DebugContext#indent() indentation} scope. *

      * Example usage: * diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/JavaMethodContext.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/JavaMethodContext.java index d400bf66891..8e1b0d8aebe 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/JavaMethodContext.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/JavaMethodContext.java @@ -25,8 +25,8 @@ package org.graalvm.compiler.debug; import jdk.vm.ci.meta.JavaMethod; /** - * Interface for objects used in Debug {@linkplain Debug#context() context} that can provide a - * {@link JavaMethod}. + * Interface for objects used in Debug {@linkplain DebugContext#context() context} that can provide + * a {@link JavaMethod}. */ public interface JavaMethodContext { JavaMethod asJavaMethod(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/KeyRegistry.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/KeyRegistry.java similarity index 67% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/KeyRegistry.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/KeyRegistry.java index 19ab80eb984..0812bceb5ec 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/KeyRegistry.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/KeyRegistry.java @@ -20,42 +20,41 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.debug.internal; +package org.graalvm.compiler.debug; import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; + +import org.graalvm.util.EconomicMap; /** - * Registry for allocating a globally unique integer id to each {@link DebugValue}. + * Registry for allocating a globally unique integer id to each {@link AbstractKey}. */ public class KeyRegistry { - private static final Map keyMap = new HashMap<>(); - private static final List debugValues = new ArrayList<>(); + private static final EconomicMap keyMap = EconomicMap.create(); + private static final List keys = new ArrayList<>(); /** - * Ensures a given debug value is registered. + * Ensures a given metric key is registered. * * @return the globally unique id for {@code value} */ - public static synchronized int register(DebugValue value) { - String name = value.getName(); + static synchronized int register(AbstractKey key) { + String name = key.getName(); if (!keyMap.containsKey(name)) { - keyMap.put(name, debugValues.size()); - debugValues.add(value); + keyMap.put(name, keys.size()); + keys.add(key); } return keyMap.get(name); } /** - * Gets a immutable view of the registered debug values. + * Gets a copy of the registered keys. * * @return a list where {@code get(i).getIndex() == i} */ - public static synchronized List getDebugValues() { - return Collections.unmodifiableList(debugValues); + public static synchronized List getKeys() { + return new ArrayList<>(keys); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Management.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Management.java index 5f818419794..0ea5d76eced 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Management.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Management.java @@ -24,12 +24,6 @@ package org.graalvm.compiler.debug; import static java.lang.Thread.currentThread; -import java.lang.management.ManagementFactory; -import java.lang.management.ThreadInfo; -import java.lang.management.ThreadMXBean; - -import javax.management.ObjectName; - public class Management { private static final com.sun.management.ThreadMXBean threadMXBean = Management.initThreadMXBean(); @@ -46,20 +40,20 @@ public class Management { private static com.sun.management.ThreadMXBean initThreadMXBean() { try { - return (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean(); + return (com.sun.management.ThreadMXBean) java.lang.management.ManagementFactory.getThreadMXBean(); } catch (Error err) { return new UnimplementedBean(); } } - public static ThreadMXBean getThreadMXBean() { + public static java.lang.management.ThreadMXBean getThreadMXBean() { return threadMXBean; } - private static class UnimplementedBean implements ThreadMXBean, com.sun.management.ThreadMXBean { + private static class UnimplementedBean implements java.lang.management.ThreadMXBean, com.sun.management.ThreadMXBean { @Override - public ObjectName getObjectName() { + public javax.management.ObjectName getObjectName() { return null; } @@ -123,22 +117,22 @@ public class Management { } @Override - public ThreadInfo getThreadInfo(long id) { + public java.lang.management.ThreadInfo getThreadInfo(long id) { return null; } @Override - public ThreadInfo[] getThreadInfo(long[] ids) { + public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids) { return null; } @Override - public ThreadInfo getThreadInfo(long id, int maxDepth) { + public java.lang.management.ThreadInfo getThreadInfo(long id, int maxDepth) { return null; } @Override - public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) { + public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) { return null; } @@ -220,12 +214,12 @@ public class Management { } @Override - public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers) { + public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers) { return null; } @Override - public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) { + public java.lang.management.ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) { return null; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigScope.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java similarity index 55% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigScope.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java index 555fa6afdb6..9b6f238efd3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigScope.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java @@ -22,35 +22,36 @@ */ package org.graalvm.compiler.debug; -import org.graalvm.compiler.debug.internal.DebugScope; - /** - * A utility for scoping a change to the current debug {@linkplain DebugScope#setConfig(DebugConfig) - * configuration}. For example: + * Tracks memory usage within a scope using {@link com.sun.management.ThreadMXBean}. This facility + * should be employed using the try-with-resources pattern: * *

      - *     DebugConfig config = ...;
      - *     try (DebugConfigScope s = new DebugConfigScope(config)) {
      - *         // ...
      - *     }
      + * try (DebugCloseable a = memUseTracker.start()) {
      + *     // the code to measure
      + * }
        * 
      */ -public class DebugConfigScope implements AutoCloseable { - - private final DebugConfig current; +public interface MemUseTrackerKey extends MetricKey { /** - * Sets the current debug {@linkplain DebugScope#setConfig(DebugConfig) configuration} to a - * given value and creates an object that when {@linkplain #close() closed} resets the - * configuration to the {@linkplain DebugScope#getConfig() current} configuration. + * Creates a point from which memory usage will be recorded if memory use tracking is + * {@linkplain DebugContext#isMemUseTrackingEnabled() enabled}. + * + * @return an object that must be closed once the activity has completed to add the memory used + * since this call to the total for this tracker */ - public DebugConfigScope(DebugConfig config) { - this.current = DebugScope.getConfig(); - DebugScope.getInstance().setConfig(config); - } + DebugCloseable start(DebugContext debug); + + /** + * Gets the current value of this tracker. + */ + long getCurrentValue(DebugContext debug); @Override - public void close() { - DebugScope.getInstance().setConfig(current); + MemUseTrackerKey doc(String string); + + static long getCurrentThreadAllocatedBytes() { + return Management.getCurrentThreadAllocatedBytes(); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKeyImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKeyImpl.java new file mode 100644 index 00000000000..0da56f729f0 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKeyImpl.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import static org.graalvm.compiler.debug.DebugCloseable.VOID_CLOSEABLE; + +import org.graalvm.util.Pair; + +class MemUseTrackerKeyImpl extends AccumulatedKey implements MemUseTrackerKey { + + MemUseTrackerKeyImpl(String format, Object arg1, Object arg2) { + super(new FlatMemUseTracker(format, arg1, arg2), format, arg1, arg2); + } + + @Override + public DebugCloseable start(DebugContext debug) { + if (debug.isMemUseTrackerEnabled(this)) { + CloseableCounter result = new MemUseCloseableCounterImpl(this, debug); + debug.currentMemUseTracker = result; + return result; + } + return VOID_CLOSEABLE; + } + + public static String valueToString(long value) { + return String.format("%d bytes", value); + } + + @Override + public String toHumanReadableFormat(long value) { + return valueToString(value); + } + + static final class FlatMemUseTracker extends AbstractKey implements MetricKey { + + FlatMemUseTracker(String nameFormat, Object nameArg1, Object nameArg2) { + super(nameFormat, nameArg1, nameArg2); + } + + @Override + protected String createName(String format, Object arg1, Object arg2) { + return super.createName(format, arg1, arg2) + FLAT_KEY_SUFFIX; + } + + @Override + public MetricKey doc(String doc) { + throw new IllegalArgumentException("Cannot set documentation for derived key " + getName()); + } + + @Override + public String getDocName() { + return null; + } + + @Override + public String toHumanReadableFormat(long value) { + return valueToString(value); + } + + @Override + public Pair toCSVFormat(long value) { + return Pair.create(String.valueOf(value), "bytes"); + } + } + + static final class MemUseCloseableCounterImpl extends CloseableCounter implements DebugCloseable { + + private final DebugContext debug; + + MemUseCloseableCounterImpl(AccumulatedKey counter, DebugContext debug) { + super(debug, debug.currentMemUseTracker, counter); + this.debug = debug; + } + + @Override + long getCounterValue() { + return MemUseTrackerKey.getCurrentThreadAllocatedBytes(); + } + + @Override + public void close() { + super.close(); + debug.currentMemUseTracker = parent; + } + } + + @Override + public Pair toCSVFormat(long value) { + return Pair.create(String.valueOf(value), "bytes"); + } + + @Override + public MemUseTrackerKey doc(String doc) { + setDoc(doc); + return this; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MetricKey.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MetricKey.java new file mode 100644 index 00000000000..e3b1af25b23 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MetricKey.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import java.util.Comparator; + +import org.graalvm.util.Pair; + +/** + * A key for a metric. + */ +public interface MetricKey { + + /** + * Converts a given value for this key to a string, scaling it to a more useful unit of + * measurement and appending a suffix indicating the unit where applicable. This representation + * is intended for human consumption. + */ + String toHumanReadableFormat(long value); + + /** + * Converts a given value for this key to a CSV format intended for automated data processing. + * + * @param value + * @return a pair where first is the {@code value} with any scaling conversion applied and + * second is the unit of measurement used for the first component (this will be the + * empty string for a simple counter) + */ + Pair toCSVFormat(long value); + + /** + * Gets the name of this key. + */ + String getName(); + + /** + * Comparator to sort keys by their names. + */ + Comparator NAME_COMPARATOR = new Comparator() { + + @Override + public int compare(MetricKey o1, MetricKey o2) { + return o1.getName().compareTo(o2.getName()); + } + + }; + + /** + * Sets the documentation for this key. + */ + MetricKey doc(String string); + + /** + * Gets the name to use when listing keys. Note that this may be different from + * {@link #getName()}. + * + * @return {@code null} if this key is derived from another key and so should not be listed + */ + String getDocName(); + + /** + * Gets the documentation for this key. + * + * @return {@code null} if this key has no documentation + */ + String getDoc(); +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java new file mode 100644 index 00000000000..54bb4e78144 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import java.io.IOException; +import java.nio.file.InvalidPathException; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; + +/** + * Miscellaneous methods for modifying and generating file system paths. + */ +public class PathUtilities { + + private static final AtomicLong globalTimeStamp = new AtomicLong(); + /** + * This generates a per thread persistent id to aid mapping related dump files with each other. + */ + private static final ThreadLocal threadDumpId = new ThreadLocal<>(); + private static final AtomicInteger dumpId = new AtomicInteger(); + + static class PerThreadSequence { + final int threadID; + HashMap sequences = new HashMap<>(2); + + PerThreadSequence(int threadID) { + this.threadID = threadID; + } + + String generateID(String extension) { + Integer box = sequences.get(extension); + if (box == null) { + sequences.put(extension, 1); + return Integer.toString(threadID); + } else { + sequences.put(extension, box + 1); + return Integer.toString(threadID) + '-' + box; + } + } + } + + private static String getThreadDumpId(String extension) { + PerThreadSequence id = threadDumpId.get(); + if (id == null) { + id = new PerThreadSequence(dumpId.incrementAndGet()); + threadDumpId.set(id); + } + return id.generateID(extension); + } + + /** + * Prepends a period (i.e., {@code '.'}) to an non-null, non-empty string representation a file + * extension if the string does not already start with a period. + * + * @return {@code ext} unmodified if it is null, empty or already starts with a period other + * {@code "." + ext} + */ + public static String formatExtension(String ext) { + if (ext == null || ext.length() == 0) { + return ""; + } + return "." + ext; + } + + /** + * Gets a time stamp for the current process. This method will always return the same value for + * the current VM execution. + */ + public static long getGlobalTimeStamp() { + if (globalTimeStamp.get() == 0) { + globalTimeStamp.compareAndSet(0, System.currentTimeMillis()); + } + return globalTimeStamp.get(); + } + + /** + * Generates a {@link Path} using the format "%s-%d_%d%s" with the {@code baseNameOption}, a + * {@link #getGlobalTimeStamp() global timestamp} , {@link #getThreadDumpId a per thread unique + * id} and an optional {@code extension}. + * + * @return the output file path or null if the flag is null + */ + public static Path getPath(OptionValues options, OptionKey baseNameOption, String extension) throws IOException { + return getPath(options, baseNameOption, extension, true); + } + + /** + * Generate a {@link Path} using the format "%s-%d_%s" with the {@code baseNameOption}, a + * {@link #getGlobalTimeStamp() global timestamp} and an optional {@code extension} . + * + * @return the output file path or null if the flag is null + */ + public static Path getPathGlobal(OptionValues options, OptionKey baseNameOption, String extension) throws IOException { + return getPath(options, baseNameOption, extension, false); + } + + private static Path getPath(OptionValues options, OptionKey baseNameOption, String extension, boolean includeThreadId) throws IOException { + if (baseNameOption.getValue(options) == null) { + return null; + } + String ext = formatExtension(extension); + final String name = includeThreadId + ? String.format("%s-%d_%s%s", baseNameOption.getValue(options), getGlobalTimeStamp(), getThreadDumpId(ext), ext) + : String.format("%s-%d%s", baseNameOption.getValue(options), getGlobalTimeStamp(), ext); + Path result = Paths.get(name); + if (result.isAbsolute()) { + return result; + } + Path dumpDir = DebugOptions.getDumpDirectory(options); + return dumpDir.resolve(name).normalize(); + } + + /** + * Gets a value based on {@code name} that can be passed to {@link Paths#get(String, String...)} + * without causing an {@link InvalidPathException}. + * + * @return {@code name} with all characters invalid for the current file system replaced by + * {@code '_'} + */ + public static String sanitizeFileName(String name) { + try { + Paths.get(name); + return name; + } catch (InvalidPathException e) { + // fall through + } + StringBuilder buf = new StringBuilder(name.length()); + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + try { + Paths.get(String.valueOf(c)); + } catch (InvalidPathException e) { + buf.append('_'); + } + buf.append(c); + } + return buf.toString(); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/ScopeImpl.java similarity index 52% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/ScopeImpl.java index 35261253c3c..b4f15ada43c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugScope.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/ScopeImpl.java @@ -20,26 +20,16 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.debug.internal; +package org.graalvm.compiler.debug; import java.io.PrintStream; import java.util.Iterator; -import java.util.concurrent.Callable; -import java.util.concurrent.atomic.AtomicLong; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugDumpHandler; -import org.graalvm.compiler.debug.DebugVerifyHandler; -import org.graalvm.compiler.debug.DelegatingDebugConfig; -import org.graalvm.compiler.debug.Indent; -import org.graalvm.compiler.debug.JavaMethodContext; -import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.TopLevelDebugConfig; +import org.graalvm.compiler.debug.DebugContext.DisabledScope; import jdk.vm.ci.meta.JavaMethod; -public final class DebugScope implements Debug.Scope { +public final class ScopeImpl implements DebugContext.Scope { private final class IndentImpl implements Indent { @@ -122,88 +112,45 @@ public final class DebugScope implements Debug.Scope { } } - /** - * Interface for an additional information object per scope. The information object will be - * given to child scopes, but can be explicitly set with - * {@link DebugScope#enhanceWithExtraInfo(CharSequence, ExtraInfo, boolean, Object...)} - */ - public interface ExtraInfo { - - } - - private static final ThreadLocal instanceTL = new ThreadLocal<>(); - private static final ThreadLocal lastClosedTL = new ThreadLocal<>(); - private static final ThreadLocal configTL = new ThreadLocal<>(); - private static final ThreadLocal lastExceptionThrownTL = new ThreadLocal<>(); - - private final DebugScope parent; - private final DebugConfig parentConfig; + private final DebugContext owner; + private final ScopeImpl parent; private final boolean sandbox; private IndentImpl lastUsedIndent; private boolean logScopeName; private final Object[] context; - private DebugValueMap valueMap; - private String qualifiedName; private final String unqualifiedName; - private final ExtraInfo extraInfo; - - private static final AtomicLong uniqueScopeId = new AtomicLong(); - private final long scopeId; - private static final char SCOPE_SEP = '.'; private boolean countEnabled; private boolean timeEnabled; private boolean memUseTrackingEnabled; private boolean verifyEnabled; - private boolean methodMetricsEnabled; private int currentDumpLevel; private int currentLogLevel; private PrintStream output; - - public static long getCurrentGlobalScopeId() { - return uniqueScopeId.get(); - } - - public static DebugScope getInstance() { - DebugScope result = instanceTL.get(); - if (result == null) { - DebugScope topLevelDebugScope = new DebugScope(Thread.currentThread()); - instanceTL.set(topLevelDebugScope); - return topLevelDebugScope; - } else { - return result; - } - } - - public static DebugConfig getConfig() { - return configTL.get(); - } + private boolean interceptDisabled; static final Object[] EMPTY_CONTEXT = new Object[0]; - private DebugScope(Thread thread) { - this(thread.getName(), null, uniqueScopeId.incrementAndGet(), null, false); - computeValueMap(thread.getName()); - DebugValueMap.registerTopLevel(getValueMap()); + ScopeImpl(DebugContext owner, Thread thread) { + this(owner, thread.getName(), null, false); } - private DebugScope(String unqualifiedName, DebugScope parent, long scopeId, ExtraInfo metaInfo, boolean sandbox, Object... context) { + ScopeImpl(DebugContext owner, String unqualifiedName, ScopeImpl parent, boolean sandbox, Object... context) { + this.owner = owner; this.parent = parent; this.sandbox = sandbox; - this.parentConfig = getConfig(); this.context = context; - this.scopeId = scopeId; this.unqualifiedName = unqualifiedName; - this.extraInfo = metaInfo; if (parent != null) { logScopeName = !unqualifiedName.equals(""); + this.interceptDisabled = parent.interceptDisabled; } else { logScopeName = true; } @@ -212,84 +159,21 @@ public final class DebugScope implements Debug.Scope { assert context != null; } - private void computeValueMap(String name) { - if (parent != null) { - for (DebugValueMap child : parent.getValueMap().getChildren()) { - if (child.getName().equals(name)) { - this.valueMap = child; - return; - } - } - this.valueMap = new DebugValueMap(name); - parent.getValueMap().addChild(this.valueMap); - } else { - this.valueMap = new DebugValueMap(name); - } - } - @Override public void close() { - instanceTL.set(parent); - configTL.set(parentConfig); - lastClosedTL.set(this); + owner.currentScope = parent; + owner.lastClosedScope = this; + } + + boolean isTopLevel() { + return parent == null; } public boolean isDumpEnabled(int dumpLevel) { - assert dumpLevel > 0; + assert dumpLevel >= 0; return currentDumpLevel >= dumpLevel; } - /** - * Enable dumping at the new {@code dumpLevel} for the remainder of enclosing scopes. This only - * works if a {@link TopLevelDebugConfig} was installed at a higher scope. - * - * @param dumpLevel - */ - public static void setDumpLevel(int dumpLevel) { - TopLevelDebugConfig config = fetchTopLevelDebugConfig("setDebugLevel"); - if (config != null) { - config.override(DelegatingDebugConfig.Level.DUMP, dumpLevel); - recursiveUpdateFlags(); - } - } - - /** - * Enable logging at the new {@code logLevel} for the remainder of enclosing scopes. This only - * works if a {@link TopLevelDebugConfig} was installed at a higher scope. - * - * @param logLevel - */ - public static void setLogLevel(int logLevel) { - TopLevelDebugConfig config = fetchTopLevelDebugConfig("setLogLevel"); - if (config != null) { - config.override(DelegatingDebugConfig.Level.LOG, logLevel); - config.delegate(DelegatingDebugConfig.Feature.LOG_METHOD); - recursiveUpdateFlags(); - } - } - - private static void recursiveUpdateFlags() { - DebugScope c = DebugScope.getInstance(); - while (c != null) { - c.updateFlags(); - c = c.parent; - } - } - - private static TopLevelDebugConfig fetchTopLevelDebugConfig(String msg) { - DebugConfig config = getConfig(); - if (config instanceof TopLevelDebugConfig) { - return (TopLevelDebugConfig) config; - } else { - if (config == null) { - TTY.println("DebugScope.%s ignored because debugging is disabled", msg); - } else { - TTY.println("DebugScope.%s ignored because top level delegate config missing", msg); - } - return null; - } - } - public boolean isVerifyEnabled() { return verifyEnabled; } @@ -307,57 +191,35 @@ public final class DebugScope implements Debug.Scope { return timeEnabled; } - public boolean isMethodMeterEnabled() { - return methodMetricsEnabled; - } - public boolean isMemUseTrackingEnabled() { return memUseTrackingEnabled; } public void log(int logLevel, String msg, Object... args) { + assert owner.checkNoConcurrentAccess(); if (isLogEnabled(logLevel)) { getLastUsedIndent().log(logLevel, msg, args); } } - public ExtraInfo getExtraInfo() { - return extraInfo; - } - - public long scopeId() { - return scopeId; - } - public void dump(int dumpLevel, Object object, String formatString, Object... args) { + assert isDumpEnabled(dumpLevel); if (isDumpEnabled(dumpLevel)) { DebugConfig config = getConfig(); if (config != null) { - String message = String.format(formatString, args); for (DebugDumpHandler dumpHandler : config.dumpHandlers()) { - dumpHandler.dump(object, message); + dumpHandler.dump(owner, object, formatString, args); } } } } - /** - * This method exists mainly to allow a debugger (e.g., Eclipse) to force dump a graph. - */ - public static void forceDump(Object object, String format, Object... args) { - DebugConfig config = getConfig(); - if (config != null) { - String message = String.format(format, args); - for (DebugDumpHandler dumpHandler : config.dumpHandlers()) { - dumpHandler.dump(object, message); - } - } else { - TTY.println("Forced dump ignored because debugging is disabled - use -Dgraal.Dump=xxx"); - } + private DebugConfig getConfig() { + return owner.currentConfig; } /** - * @see Debug#verify(Object, String) + * @see DebugContext#verify(Object, String) */ public void verify(Object object, String formatString, Object... args) { if (isVerifyEnabled()) { @@ -365,15 +227,15 @@ public final class DebugScope implements Debug.Scope { if (config != null) { String message = String.format(formatString, args); for (DebugVerifyHandler handler : config.verifyHandlers()) { - handler.verify(object, message); + handler.verify(owner, object, message); } } } } /** - * Creates and enters a new debug scope which is either a child of the current scope or a - * disjoint top level scope. + * Creates and enters a new scope which is either a child of the current scope or a disjoint top + * level scope. * * @param name the name of the new scope * @param sandboxConfig the configuration to use for a new top level scope, or null if the new @@ -381,83 +243,107 @@ public final class DebugScope implements Debug.Scope { * @param newContextObjects objects to be appended to the debug context * @return the new scope which will be exited when its {@link #close()} method is called */ - public DebugScope scope(CharSequence name, DebugConfig sandboxConfig, Object... newContextObjects) { - DebugScope newScope = null; + public ScopeImpl scope(CharSequence name, DebugConfig sandboxConfig, Object... newContextObjects) { + ScopeImpl newScope = null; if (sandboxConfig != null) { - newScope = new DebugScope(name.toString(), this, uniqueScopeId.incrementAndGet(), null, true, newContextObjects); - configTL.set(sandboxConfig); + newScope = new ScopeImpl(owner, name.toString(), this, true, newContextObjects); } else { - newScope = this.createChild(name.toString(), this.extraInfo, newContextObjects); + newScope = this.createChild(name.toString(), newContextObjects); } - instanceTL.set(newScope); - newScope.updateFlags(); + newScope.updateFlags(owner.currentConfig); return newScope; } - public DebugScope enhanceWithExtraInfo(CharSequence name, ExtraInfo newInfo, boolean newId, Object... newContext) { - DebugScope newScope = createChild(name.toString(), newInfo, newId ? uniqueScopeId.incrementAndGet() : this.scopeId, newContext); - instanceTL.set(newScope); - newScope.updateFlags(); - return newScope; + @SuppressWarnings({"unchecked", "unused"}) + private static RuntimeException silenceException(Class type, Throwable ex) throws E { + throw (E) ex; } public RuntimeException handle(Throwable e) { - DebugScope lastClosed = lastClosedTL.get(); - assert lastClosed.parent == this : "Debug.handle() used with no matching Debug.scope(...) or Debug.sandbox(...)"; - if (e != lastExceptionThrownTL.get()) { - RuntimeException newException = null; - instanceTL.set(lastClosed); - try (DebugScope s = lastClosed) { - newException = s.interceptException(e); - } - assert instanceTL.get() == this; - assert lastClosed == lastClosedTL.get(); - if (newException == null) { - lastExceptionThrownTL.set(e); + try { + if (owner.lastClosedScope instanceof ScopeImpl) { + ScopeImpl lastClosed = (ScopeImpl) owner.lastClosedScope; + assert lastClosed.parent == this : "DebugContext.handle() used without closing a scope opened by DebugContext.scope(...) or DebugContext.sandbox(...) " + + "or an exception occurred while opening a scope"; + if (e != owner.lastExceptionThrown) { + RuntimeException newException = null; + // Make the scope in which the exception was thrown + // the current scope again. + owner.currentScope = lastClosed; + + // When this try block exits, the above action will be undone + try (ScopeImpl s = lastClosed) { + newException = s.interceptException(e); + } + + // Checks that the action really is undone + assert owner.currentScope == this; + assert lastClosed == owner.lastClosedScope; + + if (newException == null) { + owner.lastExceptionThrown = e; + } else { + owner.lastExceptionThrown = newException; + throw newException; + } + } + } else if (owner.lastClosedScope == null) { + throw new AssertionError("DebugContext.handle() used without closing a scope opened by DebugContext.scope(...) or DebugContext.sandbox(...) " + + "or an exception occurred while opening a scope"); } else { - lastExceptionThrownTL.set(newException); - throw newException; + assert owner.lastClosedScope instanceof DisabledScope : owner.lastClosedScope; } + } catch (Throwable t) { + t.initCause(e); + throw t; } + if (e instanceof Error) { throw (Error) e; } if (e instanceof RuntimeException) { throw (RuntimeException) e; } - throw new RuntimeException(e); + throw silenceException(RuntimeException.class, e); } - private void updateFlags() { - DebugConfig config = getConfig(); + void updateFlags(DebugConfig config) { if (config == null) { countEnabled = false; memUseTrackingEnabled = false; timeEnabled = false; verifyEnabled = false; - currentDumpLevel = 0; - methodMetricsEnabled = false; + currentDumpLevel = -1; // Be pragmatic: provide a default log stream to prevent a crash if the stream is not // set while logging output = TTY.out; } else { - countEnabled = config.isCountEnabled(); - memUseTrackingEnabled = config.isMemUseTrackingEnabled(); - timeEnabled = config.isTimeEnabled(); - verifyEnabled = config.isVerifyEnabled(); + countEnabled = config.isCountEnabled(this); + memUseTrackingEnabled = config.isMemUseTrackingEnabled(this); + timeEnabled = config.isTimeEnabled(this); + verifyEnabled = config.isVerifyEnabled(this); output = config.output(); - currentDumpLevel = config.getDumpLevel(); - currentLogLevel = config.getLogLevel(); - methodMetricsEnabled = config.isMethodMeterEnabled(); + currentDumpLevel = config.getDumpLevel(this); + currentLogLevel = config.getLogLevel(this); } } + DebugCloseable disableIntercept() { + boolean previous = interceptDisabled; + interceptDisabled = true; + return new DebugCloseable() { + @Override + public void close() { + interceptDisabled = previous; + } + }; + } + @SuppressWarnings("try") private RuntimeException interceptException(final Throwable e) { - final DebugConfig config = getConfig(); - if (config != null) { - try (DebugScope s = scope("InterceptException", null, e)) { - return config.interceptException(e); + if (!interceptDisabled && owner.currentConfig != null) { + try (ScopeImpl s = scope("InterceptException", null, e)) { + return owner.currentConfig.interceptException(owner, e); } catch (Throwable t) { return new RuntimeException("Exception while intercepting exception", t); } @@ -465,38 +351,20 @@ public final class DebugScope implements Debug.Scope { return null; } - private DebugValueMap getValueMap() { - if (valueMap == null) { - computeValueMap(unqualifiedName); - } - return valueMap; - } - - long getCurrentValue(int index) { - return getValueMap().getCurrentValue(index); - } - - void setCurrentValue(int index, long l) { - getValueMap().setCurrentValue(index, l); - } - - private DebugScope createChild(String newName, ExtraInfo newInfo, Object[] newContext) { - return new DebugScope(newName, this, this.scopeId, newInfo, false, newContext); - } - - private DebugScope createChild(String newName, ExtraInfo newInfo, long newId, Object[] newContext) { - return new DebugScope(newName, this, newId, newInfo, false, newContext); + private ScopeImpl createChild(String newName, Object[] newContext) { + return new ScopeImpl(owner, newName, this, false, newContext); } + @Override public Iterable getCurrentContext() { - final DebugScope scope = this; + final ScopeImpl scope = this; return new Iterable() { @Override public Iterator iterator() { return new Iterator() { - DebugScope currentScope = scope; + ScopeImpl currentScope = scope; int objectIndex; @Override @@ -530,23 +398,7 @@ public final class DebugScope implements Debug.Scope { }; } - public static T call(Callable callable) { - try { - return callable.call(); - } catch (Exception e) { - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else { - throw new RuntimeException(e); - } - } - } - - public void setConfig(DebugConfig newConfig) { - configTL.set(newConfig); - updateFlags(); - } - + @Override public String getQualifiedName() { if (qualifiedName == null) { if (parent == null) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TTY.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TTY.java index f7bc3d7bd74..87caf09f237 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TTY.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TTY.java @@ -42,7 +42,7 @@ public class TTY { /** * Support for thread-local suppression of {@link TTY}. */ - public static class Filter { + public static class Filter implements AutoCloseable { private LogStream previous; private final Thread thread = Thread.currentThread(); @@ -87,6 +87,16 @@ public class TTY { log.set(LogStream.SINK); } + /** + * Creates an object that will overwrite {@link TTY} for the current thread with a custom + * log stream. To revert the overwritten state to how it was before this call, the + * {@link #remove()} method must be called on this filter object. + */ + public Filter(LogStream newStream) { + previous = out(); + log.set(newStream); + } + /** * Reverts the suppression state of {@link TTY} to how it was before this object was * constructed. @@ -97,6 +107,11 @@ public class TTY { log.set(previous); } } + + @Override + public void close() { + remove(); + } } /** diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimeSource.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimeSource.java index 8933be09140..1f0d98e23f7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimeSource.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimeSource.java @@ -22,14 +22,12 @@ */ package org.graalvm.compiler.debug; -import java.lang.management.ThreadMXBean; - /** * A consistent source of timing data that should be used by all facilities in the debug package. */ public class TimeSource { private static final boolean USING_BEAN; - private static final ThreadMXBean threadMXBean; + private static final java.lang.management.ThreadMXBean threadMXBean; static { threadMXBean = Management.getThreadMXBean(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugTimer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKey.java similarity index 76% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugTimer.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKey.java index f05d251396c..2e0120f74b1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugTimer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKey.java @@ -34,45 +34,36 @@ import java.util.concurrent.TimeUnit; * } * */ -public interface DebugTimer { +public interface TimerKey extends MetricKey { /** - * Starts this timer if timing is {@linkplain Debug#isTimeEnabled() enabled} or this is an - * {@linkplain #isConditional() unconditional} timer. + * Starts this timer. * * @return an object that must be closed once the activity has completed to add the elapsed time * since this call to the total for this timer */ - DebugCloseable start(); - - /** - * Sets a flag determining if this timer is only enabled if timing is - * {@link Debug#isTimeEnabled() enabled}. - */ - void setConditional(boolean flag); - - /** - * Determines if this timer is only enabled if timing is {@link Debug#isTimeEnabled() enabled}. - */ - boolean isConditional(); + DebugCloseable start(DebugContext debug); /** * Gets the current value of this timer. */ - long getCurrentValue(); + long getCurrentValue(DebugContext debug); /** * Gets the time unit of this timer. */ TimeUnit getTimeUnit(); + @Override + TimerKey doc(String string); + /** * Gets the timer recording the amount time spent within a timed scope minus the time spent in * any nested timed scopes. * * @return null if this timer does not support flat timing */ - default DebugTimer getFlat() { + default TimerKey getFlat() { return null; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java new file mode 100644 index 00000000000..d30ddddc6cf --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.debug; + +import static org.graalvm.compiler.debug.DebugCloseable.VOID_CLOSEABLE; + +import java.util.concurrent.TimeUnit; + +import org.graalvm.util.Pair; + +final class TimerKeyImpl extends AccumulatedKey implements TimerKey { + static class FlatTimer extends AbstractKey implements TimerKey { + private TimerKeyImpl accm; + + FlatTimer(String nameFormat, Object nameArg1, Object nameArg2) { + super(nameFormat, nameArg1, nameArg2); + } + + @Override + protected String createName(String format, Object arg1, Object arg2) { + return super.createName(format, arg1, arg2) + FLAT_KEY_SUFFIX; + } + + @Override + public String toHumanReadableFormat(long value) { + return valueToString(value); + } + + @Override + public TimeUnit getTimeUnit() { + return accm.getTimeUnit(); + } + + @Override + public DebugCloseable start(DebugContext debug) { + return accm.start(debug); + } + + @Override + public Pair toCSVFormat(long value) { + return TimerKeyImpl.toCSVFormatHelper(value); + } + + @Override + public TimerKey doc(String doc) { + throw new IllegalArgumentException("Cannot set documentation for derived key " + getName()); + } + + @Override + public String getDocName() { + return null; + } + } + + TimerKeyImpl(String nameFormat, Object nameArg1, Object nameArg2) { + super(new FlatTimer(nameFormat, nameArg1, nameArg2), nameFormat, nameArg1, nameArg2); + ((FlatTimer) flat).accm = this; + } + + @Override + public DebugCloseable start(DebugContext debug) { + if (debug.isTimerEnabled(this)) { + Timer result = new Timer(this, debug); + debug.currentTimer = result; + return result; + } else { + return VOID_CLOSEABLE; + } + } + + public static String valueToString(long value) { + return String.format("%d.%d ms", value / 1000000, (value / 100000) % 10); + } + + @Override + public TimerKey getFlat() { + return (FlatTimer) flat; + } + + @Override + public String toHumanReadableFormat(long value) { + return valueToString(value); + } + + @Override + public TimeUnit getTimeUnit() { + return TimeUnit.NANOSECONDS; + } + + final class Timer extends CloseableCounter implements DebugCloseable { + final DebugContext debug; + + Timer(AccumulatedKey counter, DebugContext debug) { + super(debug, debug.currentTimer, counter); + this.debug = debug; + } + + @Override + public void close() { + super.close(); + debug.currentTimer = parent; + } + + @Override + protected long getCounterValue() { + return TimeSource.getTimeNS(); + } + + } + + @Override + public Pair toCSVFormat(long value) { + return toCSVFormatHelper(value); + } + + static Pair toCSVFormatHelper(long value) { + return Pair.create(Long.toString(value / 1000), "us"); + } + + @Override + public TimerKey doc(String doc) { + setDoc(doc); + return this; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/CounterImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/CounterImpl.java deleted file mode 100644 index 5732cff75c8..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/CounterImpl.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug.internal; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; - -public abstract class CounterImpl extends DebugValue implements DebugCounter { - - public CounterImpl(String name, boolean conditional) { - super(name, conditional); - if (isEnabled()) { - // Allows for zero counters to be shown - getCurrentValue(); - } - } - - @Override - public void increment() { - add(1); - } - - @Override - public String rawUnit() { - return ""; - } - - @Override - public String toRawString(long value) { - return Long.toString(value); - } - - @Override - public String toString(long value) { - return Long.toString(value); - } - - private static final class InterceptingCounterImpl extends CounterImpl { - - private InterceptingCounterImpl(String name, boolean conditional) { - super(name, conditional); - } - - @Override - public void add(long value) { - if (isEnabled()) { - if (Debug.isMethodMeterEnabled()) { - MethodMetricsImpl.addToCurrentScopeMethodMetrics(getName(), value); - } - super.addToCurrentValue(value); - } - } - } - - private static final class PlainCounterImpl extends CounterImpl { - - private PlainCounterImpl(String name, boolean conditional) { - super(name, conditional); - } - - @Override - public void add(long value) { - if (isEnabled()) { - super.addToCurrentValue(value); - } - } - } - - public static DebugCounter create(String name, boolean conditional, boolean intercepting) { - if (intercepting) { - return new InterceptingCounterImpl(name, conditional); - } - return new PlainCounterImpl(name, conditional); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugHistogramAsciiPrinter.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugHistogramAsciiPrinter.java deleted file mode 100644 index 7c715152e26..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugHistogramAsciiPrinter.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug.internal; - -import java.io.PrintStream; -import java.util.Arrays; -import java.util.List; - -import org.graalvm.compiler.debug.DebugHistogram; -import org.graalvm.compiler.debug.DebugHistogram.CountedValue; -import org.graalvm.compiler.debug.DebugHistogram.Printer; - -/** - * Renders a textual representation of a histogram to a given print stream. - */ -public class DebugHistogramAsciiPrinter implements Printer { - - public static final int NumberSize = 10; - public static final int DefaultNameSize = 50; - public static final int DefaultBarSize = 100; - public static final int DefaultScale = 1; - - private final PrintStream os; - private final int limit; - private final int nameSize; - private final int barSize; - private final int scale; - - public DebugHistogramAsciiPrinter(PrintStream os) { - this(os, Integer.MAX_VALUE, DefaultNameSize, DefaultBarSize, DefaultScale); - } - - /** - * @param os where to print - * @param limit limits printing to the {@code limit} most frequent values - * @param nameSize the width of the value names column - * @param barSize the width of the value frequency column - * @param scale a factor by which every result is divided - */ - public DebugHistogramAsciiPrinter(PrintStream os, int limit, int nameSize, int barSize, int scale) { - this.os = os; - this.limit = limit; - this.nameSize = nameSize; - this.barSize = barSize; - this.scale = scale; - } - - @Override - public void print(DebugHistogram histogram) { - List list = histogram.getValues(); - if (list.isEmpty()) { - os.printf("%s is empty.%n", histogram.getName()); - return; - } - - // Sum up the total number of elements. - long total = list.stream().mapToLong(CountedValue::getCount).sum(); - - // Print header. - os.printf("%s has %d unique elements and %d total elements:%n", histogram.getName(), list.size(), total / scale); - - long max = list.get(0).getCount() / scale; - final int lineSize = nameSize + NumberSize + barSize + 10; - printLine(os, '-', lineSize); - String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n"; - for (int i = 0; i < list.size() && i < limit; ++i) { - CountedValue cv = list.get(i); - long value = cv.getCount() / scale; - char[] bar = new char[(int) (((double) value / (double) max) * barSize)]; - Arrays.fill(bar, '='); - String objectString = String.valueOf(cv.getValue()); - if (objectString.length() > nameSize) { - objectString = objectString.substring(0, nameSize - 3) + "..."; - } - os.printf(formatString, objectString, value, new String(bar)); - } - printLine(os, '-', lineSize); - } - - private static void printLine(PrintStream printStream, char c, int lineSize) { - char[] charArr = new char[lineSize]; - Arrays.fill(charArr, c); - printStream.printf("%s%n", new String(charArr)); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugHistogramImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugHistogramImpl.java deleted file mode 100644 index 1348cc3712a..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugHistogramImpl.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug.internal; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; - -import org.graalvm.compiler.debug.DebugHistogram; - -public class DebugHistogramImpl implements DebugHistogram { - - private final String name; - private HashMap map = new HashMap<>(); - - public DebugHistogramImpl(String name) { - this.name = name; - } - - @Override - public void add(Object value) { - CountedValue cv = map.get(value); - if (cv == null) { - map.put(value, new CountedValue(1, value)); - } else { - cv.inc(); - } - } - - @Override - public void add(Object value, long count) { - CountedValue cv = map.get(value); - if (cv == null) { - map.put(value, new CountedValue(count, value)); - } else { - cv.add(count); - } - } - - @Override - public String getName() { - return name; - } - - @Override - public List getValues() { - ArrayList res = new ArrayList<>(map.values()); - Collections.sort(res); - return res; - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugHistogramRPrinter.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugHistogramRPrinter.java deleted file mode 100644 index a2ee8112ab7..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugHistogramRPrinter.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug.internal; - -import java.io.PrintStream; -import java.util.List; - -import org.graalvm.compiler.debug.DebugHistogram; -import org.graalvm.compiler.debug.DebugHistogram.CountedValue; -import org.graalvm.compiler.debug.DebugHistogram.Printer; - -/** - * Renders a histogram as an R script to a given print stream. The R script emitted for a histogram - * is a simple set of statements for defining a vector of named objects. - */ -public class DebugHistogramRPrinter implements Printer { - - private PrintStream os; - private int limit; - - public DebugHistogramRPrinter(PrintStream os) { - this(os, Integer.MAX_VALUE); - } - - /** - * @param os where to print - * @param limit limits printing to the {@code limit} most frequent values - */ - public DebugHistogramRPrinter(PrintStream os, int limit) { - this.os = os; - this.limit = limit; - } - - @Override - public void print(DebugHistogram histogram) { - List list = histogram.getValues(); - if (list.isEmpty()) { - return; - } - - String var = histogram.getName().replace('-', '.').replace(' ', '_'); - os.print(var + " <- c("); - for (int i = 0; i < list.size() && i < limit; ++i) { - CountedValue cv = list.get(i); - if (i != 0) { - os.print(", "); - } - os.print(cv.getCount()); - } - os.println(");"); - - os.print("names(" + var + ") <- c("); - for (int i = 0; i < list.size() && i < limit; ++i) { - CountedValue cv = list.get(i); - if (i != 0) { - os.print(", "); - } - os.print("\"" + cv.getValue() + "\""); - } - os.println(");"); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValuesPrinter.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValuesPrinter.java deleted file mode 100644 index 90af22bf09d..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/DebugValuesPrinter.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug.internal; - -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueFile; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueHumanReadable; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueSummary; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueThreadFilter; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.SuppressZeroDebugValues; - -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import org.graalvm.compiler.debug.CSVUtil; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.debug.LogStream; -import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; -import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; - -/** - * Facility for printing the {@linkplain KeyRegistry#getDebugValues() values} collected across all - * {@link DebugValueMap#getTopLevelMaps() threads}. - */ -public class DebugValuesPrinter { - private static final String COMPUTER_READABLE_FMT = CSVUtil.buildFormatString("%s", "%s", "%s", "%s"); - private static final char SCOPE_DELIMITER = '.'; - private final MethodMetricsPrinter mmPrinter; - - public DebugValuesPrinter() { - this(null); - } - - public DebugValuesPrinter(MethodMetricsPrinter mmPrinter) { - this.mmPrinter = mmPrinter; - } - - public void printDebugValues() throws GraalError { - TTY.println(); - TTY.println(""); - List topLevelMaps = DebugValueMap.getTopLevelMaps(); - List debugValues = KeyRegistry.getDebugValues(); - if (debugValues.size() > 0) { - try { - ArrayList sortedValues = new ArrayList<>(debugValues); - Collections.sort(sortedValues); - - String summary = DebugValueSummary.getValue(); - if (summary == null) { - summary = "Complete"; - } - if (DebugValueThreadFilter.getValue() != null && topLevelMaps.size() != 0) { - topLevelMaps = topLevelMaps.stream().filter(map -> Pattern.compile(DebugValueThreadFilter.getValue()).matcher(map.getName()).find()).collect(Collectors.toList()); - if (topLevelMaps.size() == 0) { - TTY.println("Warning: DebugValueThreadFilter=%s eliminated all maps so nothing will be printed", DebugValueThreadFilter.getValue()); - } - } - switch (summary) { - case "Name": { - LogStream log = getLogStream(); - printSummary(log, topLevelMaps, sortedValues); - break; - } - case "Partial": { - DebugValueMap globalMap = new DebugValueMap("Global"); - for (DebugValueMap map : topLevelMaps) { - flattenChildren(map, globalMap); - } - globalMap.normalize(); - LogStream log = getLogStream(); - printMap(log, new DebugValueScope(null, globalMap), sortedValues); - break; - } - case "Complete": { - DebugValueMap globalMap = new DebugValueMap("Global"); - for (DebugValueMap map : topLevelMaps) { - globalMap.addChild(map); - } - globalMap.group(); - globalMap.normalize(); - LogStream log = getLogStream(); - printMap(log, new DebugValueScope(null, globalMap), sortedValues); - break; - } - case "Thread": - for (DebugValueMap map : topLevelMaps) { - TTY.println("Showing the results for thread: " + map.getName()); - map.group(); - map.normalize(); - LogStream log = getLogStream(map.getName().replace(' ', '_')); - printMap(log, new DebugValueScope(null, map), sortedValues); - } - break; - default: - throw new GraalError("Unknown summary type: %s", summary); - } - for (DebugValueMap topLevelMap : topLevelMaps) { - topLevelMap.reset(); - } - } catch (Throwable e) { - // Don't want this to change the exit status of the VM - PrintStream err = System.err; - err.println("Error while printing debug values:"); - e.printStackTrace(); - } - } - if (mmPrinter != null) { - mmPrinter.printMethodMetrics(MethodMetricsImpl.collectedMetrics()); - } - TTY.println(""); - } - - private static LogStream getLogStream() { - return getLogStream(null); - } - - private static LogStream getLogStream(String prefix) { - String debugValueFile = DebugValueFile.getValue(); - if (debugValueFile != null) { - try { - final String fileName; - if (prefix != null) { - fileName = prefix + '-' + debugValueFile; - } else { - fileName = debugValueFile; - } - LogStream logStream = new LogStream(new FileOutputStream(fileName)); - TTY.println("Writing debug values to '%s'", fileName); - return logStream; - } catch (FileNotFoundException e) { - TTY.println("Warning: Could not open debug value log file: %s (defaulting to TTY)", e.getMessage()); - } - } - return TTY.out(); - } - - private void flattenChildren(DebugValueMap map, DebugValueMap globalMap) { - globalMap.addChild(map); - for (DebugValueMap child : map.getChildren()) { - flattenChildren(child, globalMap); - } - map.clearChildren(); - } - - private void printSummary(LogStream log, List topLevelMaps, List debugValues) { - DebugValueMap result = new DebugValueMap("Summary"); - for (int i = debugValues.size() - 1; i >= 0; i--) { - DebugValue debugValue = debugValues.get(i); - int index = debugValue.getIndex(); - long total = collectTotal(topLevelMaps, index); - result.setCurrentValue(index, total); - } - printMap(log, new DebugValueScope(null, result), debugValues); - } - - private long collectTotal(List maps, int index) { - long total = 0; - for (int i = 0; i < maps.size(); i++) { - DebugValueMap map = maps.get(i); - total += map.getCurrentValue(index); - total += collectTotal(map.getChildren(), index); - } - return total; - } - - /** - * Tracks the scope when printing a {@link DebugValueMap}, allowing "empty" scopes to be - * omitted. An empty scope is one in which there are no (nested) non-zero debug values. - */ - static class DebugValueScope { - - final DebugValueScope parent; - final int level; - final DebugValueMap map; - private boolean printed; - - DebugValueScope(DebugValueScope parent, DebugValueMap map) { - this.parent = parent; - this.map = map; - this.level = parent == null ? 0 : parent.level + 1; - } - - public void print(LogStream log) { - if (!printed) { - printed = true; - if (parent != null) { - parent.print(log); - } - printIndent(log, level); - log.printf("%s%n", map.getName()); - } - } - - public String toRawString() { - return toRaw(new StringBuilder()).toString(); - } - - private StringBuilder toRaw(StringBuilder stringBuilder) { - final StringBuilder sb = (parent == null) ? stringBuilder : parent.toRaw(stringBuilder).append(SCOPE_DELIMITER); - return sb.append(map.getName()); - } - - } - - private void printMap(LogStream log, DebugValueScope scope, List debugValues) { - if (DebugValueHumanReadable.getValue()) { - printMapHumanReadable(log, scope, debugValues); - } else { - printMapComputerReadable(log, scope, debugValues); - } - } - - private void printMapComputerReadable(LogStream log, DebugValueScope scope, List debugValues) { - - for (DebugValue value : debugValues) { - long l = scope.map.getCurrentValue(value.getIndex()); - if (l != 0 || !SuppressZeroDebugValues.getValue()) { - CSVUtil.Escape.println(log, COMPUTER_READABLE_FMT, scope.toRawString(), value.getName(), value.toRawString(l), value.rawUnit()); - } - } - - List children = scope.map.getChildren(); - for (int i = 0; i < children.size(); i++) { - DebugValueMap child = children.get(i); - printMapComputerReadable(log, new DebugValueScope(scope, child), debugValues); - } - } - - private void printMapHumanReadable(LogStream log, DebugValueScope scope, List debugValues) { - - for (DebugValue value : debugValues) { - long l = scope.map.getCurrentValue(value.getIndex()); - if (l != 0 || !SuppressZeroDebugValues.getValue()) { - scope.print(log); - printIndent(log, scope.level + 1); - log.println(value.getName() + "=" + value.toString(l)); - } - } - - List children = scope.map.getChildren(); - for (int i = 0; i < children.size(); i++) { - DebugValueMap child = children.get(i); - printMapHumanReadable(log, new DebugValueScope(scope, child), debugValues); - } - } - - private static void printIndent(LogStream log, int level) { - for (int i = 0; i < level; ++i) { - log.print(" "); - } - log.print("|-> "); - } - - public void clearDebugValues() { - List topLevelMaps = DebugValueMap.getTopLevelMaps(); - List debugValues = KeyRegistry.getDebugValues(); - if (debugValues.size() > 0) { - for (DebugValueMap map : topLevelMaps) { - map.reset(); - } - } - if (mmPrinter != null) { - MethodMetricsImpl.clearMM(); - } - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/MemUseTrackerImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/MemUseTrackerImpl.java deleted file mode 100644 index 789db1f9e6d..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/MemUseTrackerImpl.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug.internal; - -import static org.graalvm.compiler.debug.DebugCloseable.VOID_CLOSEABLE; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugMemUseTracker; -import org.graalvm.compiler.debug.Management; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; - -public class MemUseTrackerImpl extends AccumulatedDebugValue implements DebugMemUseTracker { - private final boolean intercepting; - - public static long getCurrentThreadAllocatedBytes() { - return Management.getCurrentThreadAllocatedBytes(); - } - - /** - * Records the most recent active tracker. - */ - private static final ThreadLocal currentTracker = new ThreadLocal<>(); - - public MemUseTrackerImpl(String name, boolean conditional, boolean intercepting) { - super(name, conditional, new DebugValue(name + "_Flat", conditional) { - - @Override - public String toString(long value) { - return valueToString(value); - } - - @Override - public String rawUnit() { - return "B"; - } - - @Override - public String toRawString(long value) { - return Long.toString(value); - } - }); - this.intercepting = intercepting; - } - - @Override - public DebugCloseable start() { - if (!isConditional() || Debug.isMemUseTrackingEnabled()) { - CloseableCounterImpl result = intercepting ? new MemUseInterceptingCloseableCounterImpl(this) : new MemUseCloseableCounterImpl(this); - currentTracker.set(result); - return result; - } else { - return VOID_CLOSEABLE; - } - } - - public static String valueToString(long value) { - return String.format("%d bytes", value); - } - - @Override - public String toString(long value) { - return valueToString(value); - } - - private static final class MemUseCloseableCounterImpl extends CloseableCounterImpl implements DebugCloseable { - - private MemUseCloseableCounterImpl(AccumulatedDebugValue counter) { - super(currentTracker.get(), counter); - } - - @Override - long getCounterValue() { - return getCurrentThreadAllocatedBytes(); - } - - @Override - public void close() { - super.close(); - currentTracker.set(parent); - } - } - - private static final class MemUseInterceptingCloseableCounterImpl extends CloseableCounterImpl implements DebugCloseable { - - private MemUseInterceptingCloseableCounterImpl(AccumulatedDebugValue counter) { - super(currentTracker.get(), counter); - } - - @Override - long getCounterValue() { - return getCurrentThreadAllocatedBytes(); - } - - @Override - public void close() { - super.close(); - currentTracker.set(parent); - } - - @Override - protected void interceptDifferenceAccm(long difference) { - if (Debug.isMethodMeterEnabled()) { - MethodMetricsImpl.addToCurrentScopeMethodMetrics(counter.getName(), difference); - } - } - - @Override - protected void interceptDifferenceFlat(long difference) { - if (Debug.isMethodMeterEnabled()) { - MethodMetricsImpl.addToCurrentScopeMethodMetrics(counter.flat.getName(), difference); - } - } - } - - @Override - public String rawUnit() { - return "B"; - } - - @Override - public String toRawString(long value) { - return Long.toString(value); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/TimerImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/TimerImpl.java deleted file mode 100644 index 6f0ae33cbdc..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/TimerImpl.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug.internal; - -import static org.graalvm.compiler.debug.DebugCloseable.VOID_CLOSEABLE; - -import java.util.concurrent.TimeUnit; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.TimeSource; -import org.graalvm.compiler.debug.internal.method.MethodMetricsImpl; - -public final class TimerImpl extends AccumulatedDebugValue implements DebugTimer { - private final boolean intercepting; - - /** - * Records the most recent active timer. - */ - private static final ThreadLocal currentTimer = new ThreadLocal<>(); - - static class FlatTimer extends DebugValue implements DebugTimer { - private TimerImpl accm; - - FlatTimer(String name, boolean conditional) { - super(name + "_Flat", conditional); - } - - @Override - public String toString(long value) { - return valueToString(value); - } - - @Override - public TimeUnit getTimeUnit() { - return accm.getTimeUnit(); - } - - @Override - public DebugCloseable start() { - return accm.start(); - } - - @Override - public String rawUnit() { - return "us"; - } - - @Override - public String toRawString(long value) { - return valueToRawString(value); - } - } - - public TimerImpl(String name, boolean conditional, boolean intercepting) { - super(name, conditional, new FlatTimer(name, conditional)); - ((FlatTimer) flat).accm = this; - this.intercepting = intercepting; - } - - @Override - public DebugCloseable start() { - if (!isConditional() || Debug.isTimeEnabled()) { - AbstractTimer result = intercepting ? new InterceptingTimer(this) : new Timer(this); - currentTimer.set(result); - return result; - } else { - return VOID_CLOSEABLE; - } - } - - public static String valueToString(long value) { - return String.format("%d.%d ms", value / 1000000, (value / 100000) % 10); - } - - @Override - public DebugTimer getFlat() { - return (FlatTimer) flat; - } - - @Override - public String toString(long value) { - return valueToString(value); - } - - @Override - public TimeUnit getTimeUnit() { - return TimeUnit.NANOSECONDS; - } - - private abstract class AbstractTimer extends CloseableCounterImpl implements DebugCloseable { - - private AbstractTimer(AccumulatedDebugValue counter) { - super(currentTimer.get(), counter); - } - - @Override - public void close() { - super.close(); - currentTimer.set(parent); - } - } - - private final class Timer extends AbstractTimer { - - private Timer(TimerImpl timer) { - super(timer); - } - - @Override - protected long getCounterValue() { - return TimeSource.getTimeNS(); - } - - } - - private final class InterceptingTimer extends AbstractTimer { - - private InterceptingTimer(TimerImpl timer) { - super(timer); - } - - @Override - protected long getCounterValue() { - return TimeSource.getTimeNS(); - } - - @Override - protected void interceptDifferenceAccm(long difference) { - if (Debug.isMethodMeterEnabled()) { - MethodMetricsImpl.addToCurrentScopeMethodMetrics(counter.getName(), difference); - } - } - - @Override - protected void interceptDifferenceFlat(long difference) { - if (Debug.isMethodMeterEnabled()) { - MethodMetricsImpl.addToCurrentScopeMethodMetrics(counter.flat.getName(), difference); - } - } - } - - @Override - public String rawUnit() { - return "us"; - } - - @Override - public String toRawString(long value) { - return valueToRawString(value); - } - - public static String valueToRawString(long value) { - return Long.toString(value / 1000); - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsImpl.java deleted file mode 100644 index de653cac885..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsImpl.java +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug.internal.method; - -import java.io.PrintStream; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.graalvm.compiler.debug.CSVUtil; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugMethodMetrics; -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.internal.DebugScope; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class MethodMetricsImpl implements DebugMethodMetrics { - - /** - * A list capturing all method metrics data of all the compiler threads. Every thread registers - * a reference to its thread local map of compilation metrics in this list. During metrics - * dumping this list is globally locked and all method entries across all threads are merged to - * a result. - */ - private static final List> threadMaps = new ArrayList<>(); - /** - * Every compiler thread carries its own map of metric data for each method and compilation it - * compiles. This data is stored in {@link ThreadLocal} maps for each compiler thread that are - * merged before metrics are reported. Storing compilation data thread locally reduces the - * locking on access of a method metric object to one point for each thread, the first access - * where the thread local is initialized. - */ - private static final ThreadLocal> threadEntries = new ThreadLocal<>(); - /** - * The lowest debug scope id that should be used during metric dumping. When a bootstrap is run - * all compilations during bootstrap are also collected if the associated debug filters match. - * Data collected during bootstrap should normally not be included in metrics for application - * compilation, thus every compilation lower than this index is ignored during metric dumping. - */ - private static long lowestCompilationDebugScopeId; - - public static class CompilationData { - /** - * A mapping of graph ids (unique ids used for the caching) to compilations. - */ - private final Map> compilations; - /** - * A pointer to a {@code MethodMetricsImpl} object. This reference is created once for every - * compilation of a method (and once for each thread, i.e. if method a is compiled by 8 - * compiler threads there will be 8 metrics objects for the given method, one local to every - * thread, this avoids synchronizing on the metrics object on every access) accessing method - * metrics for a given method. - */ - private final MethodMetricsImpl metrics; - - CompilationData(ResolvedJavaMethod method) { - compilations = new HashMap<>(8); - metrics = new MethodMetricsImpl(method); - } - - public Map> getCompilations() { - return compilations; - } - } - - private static void addThreadCompilationData(Map threadMap) { - synchronized (threadMaps) { - threadMaps.add(threadMap); - } - } - - /** - * A reference to the {@link ResolvedJavaMethod} method object. This object's identity is used - * to store metrics for each compilation. - */ - private final ResolvedJavaMethod method; - /** - * A list of all recorded compilations. This is generated during metric dumping when all thread - * local metrics are merged into one final method metrics object that is than reported - */ - private List>> collected; - /** - * A pointer to the current compilation data for the {@link MethodMetricsImpl#method} method - * which allows to avoid synchronizing over the compilation data. This reference changes for - * each compilation of the given method. It is set on the first access of this - * {@link MethodMetricsImpl} object during the call to - * {@link MethodMetricsImpl#getMethodMetrics(ResolvedJavaMethod)}. - */ - private Map currentCompilation; - - MethodMetricsImpl(ResolvedJavaMethod method) { - this.method = method; - } - - private static void clearData() { - lowestCompilationDebugScopeId = DebugScope.getCurrentGlobalScopeId(); - } - - @Override - public void addToMetric(long value, String metricName) { - if (!Debug.isMethodMeterEnabled() || value == 0) { - return; - } - assert metricName != null; - Long valueStored = currentCompilation.get(metricName); - currentCompilation.put(metricName, valueStored == null ? value : value + valueStored); - } - - @Override - public long getCurrentMetricValue(String metricName) { - assert metricName != null; - Long valueStored = currentCompilation.get(metricName); - return valueStored == null ? 0 : valueStored; - } - - @Override - public void addToMetric(long value, String format, Object arg1) { - addToMetric(value, String.format(format, arg1)); - } - - @Override - public void addToMetric(long value, String format, Object arg1, Object arg2) { - addToMetric(value, String.format(format, arg1, arg2)); - } - - @Override - public void addToMetric(long value, String format, Object arg1, Object arg2, Object arg3) { - addToMetric(value, String.format(format, arg1, arg2, arg3)); - } - - @Override - public void incrementMetric(String metricName) { - addToMetric(1, metricName); - } - - @Override - public void incrementMetric(String format, Object arg1) { - incrementMetric(String.format(format, arg1)); - } - - @Override - public void incrementMetric(String format, Object arg1, Object arg2) { - incrementMetric(String.format(format, arg1, arg2)); - } - - @Override - public void incrementMetric(String format, Object arg1, Object arg2, Object arg3) { - incrementMetric(String.format(format, arg1, arg2, arg3)); - } - - @Override - public long getCurrentMetricValue(String format, Object arg1) { - return getCurrentMetricValue(String.format(format, arg1)); - } - - @Override - public long getCurrentMetricValue(String format, Object arg1, Object arg2) { - return getCurrentMetricValue(String.format(format, arg1, arg2)); - } - - @Override - public long getCurrentMetricValue(String format, Object arg1, Object arg2, Object arg3) { - return getCurrentMetricValue(String.format(format, arg1, arg2, arg3)); - } - - @Override - public ResolvedJavaMethod getMethod() { - return method; - } - - public static DebugMethodMetrics getMethodMetrics(ResolvedJavaMethod method) { - assert method != null; - Map threadCache = threadEntries.get(); - if (threadCache == null) { - // this branch will only be executed once for each compiler thread on the first request - // of a method metric - threadCache = new HashMap<>(GraalDebugConfig.Options.MethodFilter.getValue() == null ? 128 : 16); - threadEntries.set(threadCache); - addThreadCompilationData(threadCache); - } - - CompilationData recorded = threadCache.get(method); - if (recorded == null) { - recorded = new CompilationData(method); - threadCache.put(method, recorded); - } - // pre-generate the current compilation map to avoid doing it later every time we add to a - // metric or read a current metric's value - long compilationId = DebugScope.getInstance().scopeId(); - Map currentCompilation = recorded.compilations.get(compilationId); - if (currentCompilation == null) { - // this map is generated for every distinct compilation of a unique method - currentCompilation = new HashMap<>(32); - recorded.compilations.put(compilationId, currentCompilation); - // we remember a reference to the current compilation to avoid the expensive lookup - recorded.metrics.currentCompilation = currentCompilation; - } - - return recorded.metrics; - } - - public void dumpASCII(PrintStream p) { - // we need to lock the threadmap as a concurrent call to #collectedMetrics can change the - // content of this#collected - synchronized (threadMaps) { - String methodName = method.toString(); - int maxLen = methodName.length(); - int entrySum = 0; - // get the longest entry - for (Map> compilationThreadTable : collected) { - for (Map.Entry> compilationEntry : compilationThreadTable.entrySet()) { - Map table = compilationEntry.getValue(); - if (table != null) { - for (Map.Entry entry : table.entrySet()) { - maxLen = Math.max(maxLen, entry.getKey().length()); - entrySum += entry.getValue(); - } - } - } - } - if (entrySum == 0) { - // nothing to report - return; - } - maxLen += 23; - for (int j = 0; j < maxLen; j++) { - p.print("#"); - } - p.println(); - p.println(methodName); - for (int j = 0; j < maxLen; j++) { - p.print("~"); - } - p.println(); - for (Map> compilationThreadTable : collected) { - for (Map.Entry> compilationEntry : compilationThreadTable.entrySet()) { - Map table = compilationEntry.getValue(); - if (table != null) { - if (table.values().stream().filter(x -> x > 0).count() == 0) { - continue; - } - Set> entries = table.entrySet(); - for (Map.Entry entry : entries.stream().sorted((x, y) -> x.getKey().compareTo(y.getKey())).collect(Collectors.toList())) { - long value = entry.getValue(); - // report timers in ms and memory in mb - if ((entry.getKey().endsWith("Accm") || entry.getKey().endsWith("Flat")) && - !entry.getKey().toLowerCase().contains("mem")) { - value = value / 1000000; - } - if (value == 0) { - continue; - } - p.print(String.format("%-" + String.valueOf(maxLen - 23) + "s = %20d", entry.getKey(), value)); - p.println(); - } - for (int j = 0; j < maxLen; j++) { - p.print("~"); - } - p.println(); - } - } - } - for (int j = 0; j < maxLen; j++) { - p.print("#"); - } - p.println(); - } - } - - private static final String FMT = CSVUtil.buildFormatString("%s", "%s", "%d", "%d", "%s", "%d"); - - public void dumpCSV(PrintStream p) { - // we need to lock the threadmap as a concurrent call to #collectedMetrics can change - // the content of this#collected - synchronized (threadMaps) { - String methodName = method.format("%H.%n(%p)%R"); - /* - * NOTE: the caching mechanism works by caching compilation data based on the identity - * of the resolved java method object. The identity is based on the metaspace address of - * the resolved java method object. If the class was loaded by different class loaders - * or e.g. loaded - unloaded - loaded the identity will be different. Therefore we also - * need to include the identity in the reporting of the data as it is an additional - * dimension to . - */ - String methodIdentity = String.valueOf(System.identityHashCode(method)); - int nrOfCompilations = 0; - for (Map> compilationThreadTable : collected) { - for (Map.Entry> compilationEntry : compilationThreadTable.entrySet()) { - Map table = compilationEntry.getValue(); - if (table != null) { - Set> entries = table.entrySet(); - for (Map.Entry entry : entries.stream().sorted((x, y) -> x.getKey().compareTo(y.getKey())).collect(Collectors.toList())) { - CSVUtil.Escape.println(p, FMT, methodName, methodIdentity, nrOfCompilations, compilationEntry.getKey(), entry.getKey(), entry.getValue()); - } - nrOfCompilations++; - } - } - } - } - } - - public static Collection collectedMetrics() { - synchronized (threadMaps) { - // imprecise excluding all compilations that follow, we simply do not report them - final long lastId = DebugScope.getCurrentGlobalScopeId(); - List finalMetrics = new ArrayList<>(); - Set methods = new HashSet<>(); - - // gather all methods we found - threadMaps.stream().forEach(x -> { - // snapshot the current compilations to only capture all methods compiled until now - HashMap snapShot = new HashMap<>(x); - snapShot.keySet().forEach(y -> methods.add(y)); - }); - - // for each method gather all metrics we want to report - for (ResolvedJavaMethod method : methods) { - MethodMetricsImpl impl = new MethodMetricsImpl(method); - impl.collected = new ArrayList<>(); - for (Map threadMap : threadMaps) { - CompilationData threadMethodData = threadMap.get(method); - - // not every method is necessarily compiled by all threads - if (threadMethodData != null) { - Map> snapshot = new HashMap<>(threadMethodData.compilations); - for (Map.Entry> entry : snapshot.entrySet()) { - if (entry.getKey() < lowestCompilationDebugScopeId || entry.getKey() > lastId) { - entry.setValue(null); - } - } - impl.collected.add(snapshot); - } - } - finalMetrics.add(impl); - } - - return finalMetrics; - } - } - - public static void clearMM() { - clearData(); - } - - private static final String INLINEE_PREFIX = "INLINING_SCOPE_"; - private static final boolean TRACK_INLINED_SCOPES = false; - - public static void recordInlinee(ResolvedJavaMethod root, ResolvedJavaMethod caller, ResolvedJavaMethod inlinee) { - if (TRACK_INLINED_SCOPES) { - Debug.methodMetrics(root).addToMetric(1, "INLINED_METHOD_root: caller:%s inlinee:%s", caller, inlinee); - } - } - - private static final boolean COUNT_CACHE = false; - private static final String HIT_MSG = "InterceptionCache_Hit"; - private static final String MISS_MSG = "InterceptionCache_Miss"; - private static final DebugCounter cacheHit = Debug.counter(HIT_MSG); - private static final DebugCounter cacheMiss = Debug.counter(MISS_MSG); - /** - * To avoid the lookup of a method metrics through the - * {@link MethodMetricsImpl#getMethodMetrics(ResolvedJavaMethod)} method on every global metric - * interception we thread-locally cache the last (through metric interception) - * {@link MethodMetricsImpl} object. This avoids additional map lookups and replaces them with a - * {@link DebugScope#scopeId()} call and a numerical comparison in a cache hit case. - */ - private static final ThreadLocal interceptionCache = new ThreadLocal<>(); - private static final ThreadLocal interceptionMetrics = new ThreadLocal<>(); - - public static void addToCurrentScopeMethodMetrics(String metricName, long value) { - if (COUNT_CACHE) { - if (metricName.equals(HIT_MSG) || metricName.equals(MISS_MSG)) { - return; - } - } - final DebugScope currScope = DebugScope.getInstance(); - final DebugScope.ExtraInfo metaInfo = currScope.getExtraInfo(); - final long currScopeId = currScope.scopeId(); - if (metaInfo instanceof MethodMetricsRootScopeInfo) { - ResolvedJavaMethod rootMethod = ((MethodMetricsRootScopeInfo) metaInfo).getRootMethod(); - if (metaInfo instanceof MethodMetricsInlineeScopeInfo) { - /* - * if we make use of a method filter(s) together with interception we get a problem - * with inlined methods and their scopes. Inlining will put the inlinee(s) on the - * debug scope context thus Debug.areMethodMetricsEnabled() will yield true if an - * inlinee matches a method filter. Thus we must make sure the root is defined as - * this means the root matched a method filter and therefore the inlinee can be - * safely recorded. - */ - if (TRACK_INLINED_SCOPES) { - if (threadEntries.get().get(rootMethod) != null) { - Debug.methodMetrics(rootMethod).addToMetric(value, "%s%s", INLINEE_PREFIX, metricName); - } - } - } else { - // when unboxing the thread local on access it must not be null - Long cachedId = interceptionCache.get(); - if (cachedId != null && cachedId == currScopeId) { - interceptionMetrics.get().addToMetric(value, metricName); - if (COUNT_CACHE) { - cacheHit.increment(); - } - } else { - // avoid the lookup over Debug.methodMetrics - final MethodMetricsImpl impl = (MethodMetricsImpl) getMethodMetrics(rootMethod); - impl.addToMetric(value, metricName); - // cache for next access - interceptionCache.set(currScopeId); - interceptionMetrics.set(impl); - if (COUNT_CACHE) { - cacheMiss.increment(); - } - } - } - } - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsInlineeScopeInfo.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsInlineeScopeInfo.java deleted file mode 100644 index 11f82ab49e9..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsInlineeScopeInfo.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug.internal.method; - -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.internal.DebugScope; -import org.graalvm.compiler.debug.internal.DebugScope.ExtraInfo; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class MethodMetricsInlineeScopeInfo extends MethodMetricsRootScopeInfo { - - MethodMetricsInlineeScopeInfo(ResolvedJavaMethod rootMethod) { - super(rootMethod); - } - - public static MethodMetricsInlineeScopeInfo create(ResolvedJavaMethod rootMethod) { - if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled()) { - return new MethodMetricsInlineeScopeInfo(rootMethod); - } - return null; - } - - public static MethodMetricsInlineeScopeInfo create() { - if (GraalDebugConfig.isGlobalMetricsInterceptedByMethodMetricsEnabled()) { - ExtraInfo rootInfo = DebugScope.getInstance().getExtraInfo(); - if (rootInfo instanceof MethodMetricsRootScopeInfo) { - return new MethodMetricsInlineeScopeInfo(((MethodMetricsRootScopeInfo) rootInfo).getRootMethod()); - } - } - return null; - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsPrinter.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsPrinter.java deleted file mode 100644 index e74ed661861..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsPrinter.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug.internal.method; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import org.graalvm.compiler.debug.DebugMethodMetrics; -import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; - -/** - * Interface for printing a collection of method metrics (e.g. during shutdown). - */ -public interface MethodMetricsPrinter { - - class Options { - // @formatter:off - @Option(help = "Dump method metrics to stdout on shutdown.", type = OptionType.Debug) - public static final OptionValue MethodMeterPrintAscii = new OptionValue<>(false); - @Option(help = "Dump method metrics to the given file in CSV format on shutdown.", type = OptionType.Debug) - public static final OptionValue MethodMeterFile = new OptionValue<>(null); - // @formatter:on - } - - static boolean methodMetricsDumpingEnabled() { - return MethodMetricsPrinter.Options.MethodMeterPrintAscii.getValue() || MethodMetricsPrinter.Options.MethodMeterFile.getValue() != null; - } - - /** - * Prints the metrics to a destination specified by the implementor of this interface. - * - * @param metrics the set of collected method metrics during execution as defined by - * {@link DebugMethodMetrics}. - */ - void printMethodMetrics(Collection metrics); - - class MethodMetricsASCIIPrinter implements MethodMetricsPrinter { - private final OutputStream out; - - public MethodMetricsASCIIPrinter(OutputStream out) { - this.out = out; - } - - @Override - public void printMethodMetrics(Collection metrics) { - PrintStream p = new PrintStream(out); - for (DebugMethodMetrics m : metrics) { - ((MethodMetricsImpl) m).dumpASCII(p); - p.println(); - } - } - - } - - class MethodMetricsCompositePrinter implements MethodMetricsPrinter { - private final List printers; - - public MethodMetricsCompositePrinter(MethodMetricsPrinter... p) { - printers = Arrays.asList(p); - } - - public void registerPrinter(MethodMetricsPrinter printer) { - printers.add(printer); - } - - public void unregisterPrinter(MethodMetricsPrinter printer) { - printers.remove(printer); - } - - @Override - public void printMethodMetrics(Collection metrics) { - for (MethodMetricsPrinter p : printers) { - p.printMethodMetrics(metrics); - } - } - - } - - class MethodMetricsCSVFilePrinter implements MethodMetricsPrinter { - private FileOutputStream fw; - - public MethodMetricsCSVFilePrinter() { - try { - fw = new FileOutputStream(new File(Options.MethodMeterFile.getValue())); - } catch (IOException e) { - TTY.println("Cannot create file %s for method metrics dumping:%s", Options.MethodMeterFile.getValue(), e); - throw new Error(e); - } - } - - @Override - public void printMethodMetrics(Collection metrics) { - // mm printing creates simple (R-parsable) csv files in long data format - if (fw != null && metrics != null) { - try (PrintStream p = new PrintStream(fw)) { - for (DebugMethodMetrics m : metrics) { - if (m instanceof MethodMetricsImpl) { - ((MethodMetricsImpl) m).dumpCSV(p); - p.println(); - } - } - } - try { - fw.close(); - } catch (IOException e) { - throw new Error(e); - } - } - } - - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsRootScopeInfo.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsRootScopeInfo.java deleted file mode 100644 index fd8b18d23d5..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/internal/method/MethodMetricsRootScopeInfo.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.debug.internal.method; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.internal.DebugScope; -import org.graalvm.compiler.debug.internal.DebugScope.ExtraInfo; - -import jdk.vm.ci.meta.ResolvedJavaMethod; - -public class MethodMetricsRootScopeInfo implements ExtraInfo { - protected final ResolvedJavaMethod rootMethod; - - MethodMetricsRootScopeInfo(ResolvedJavaMethod rootMethod) { - this.rootMethod = rootMethod; - } - - public ResolvedJavaMethod getRootMethod() { - return rootMethod; - } - - public static MethodMetricsRootScopeInfo create(ResolvedJavaMethod rootMethod) { - return new MethodMetricsRootScopeInfo(rootMethod); - } - - /** - * Creates and returns a {@link org.graalvm.compiler.debug.Debug.Scope scope} iff there is no - * existing {@linkplain org.graalvm.compiler.debug.internal.DebugScope.ExtraInfo extraInfo} - * object of type {@link MethodMetricsRootScopeInfo} present in the current {@link DebugScope - * scope}. - * - * @param method - * @return a new {@link org.graalvm.compiler.debug.Debug.Scope scope} or {@code null} iff there - * is already an existing one on the scope - */ - public static Debug.Scope createRootScopeIfAbsent(ResolvedJavaMethod method) { - /* - * if the current compilation is not triggered from JVMCI we need a valid context root - * method for method metrics - */ - return DebugScope.getInstance().getExtraInfo() instanceof MethodMetricsRootScopeInfo ? null : Debug.methodMetricsScope("GraalCompilerRoot", MethodMetricsRootScopeInfo.create(method), true); - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/GraphTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/GraphTest.java new file mode 100644 index 00000000000..c0c06536afc --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/GraphTest.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.graph.test; + +import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.options.OptionValues; +import org.junit.After; + +public abstract class GraphTest { + + static OptionValues getOptions() { + return Graal.getRequiredCapability(OptionValues.class); + } + + private final ThreadLocal cachedDebug = new ThreadLocal<>(); + + protected DebugContext getDebug(OptionValues options) { + DebugContext cached = cachedDebug.get(); + if (cached != null) { + if (cached.getOptions() == options) { + return cached; + } + throw new AssertionError("At most one " + DebugContext.class.getName() + " object should be created per test"); + } + DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER); + cachedDebug.set(debug); + return debug; + } + + protected DebugContext getDebug() { + return getDebug(getOptions()); + } + + @After + public void afterTest() { + DebugContext cached = cachedDebug.get(); + if (cached != null) { + cached.closeDumpHandlers(true); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java index 8d23f55727f..c16e45a599c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeMapTest.java @@ -31,13 +31,15 @@ import org.junit.Before; import org.junit.Test; import org.graalvm.compiler.api.test.Graal; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeMap; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.options.OptionValues; -public class NodeMapTest { +public class NodeMapTest extends GraphTest { @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) static final class TestNode extends Node { @@ -57,7 +59,8 @@ public class NodeMapTest { // Need to initialize HotSpotGraalRuntime before any Node class is initialized. Graal.getRuntime(); - graph = new Graph(); + OptionValues options = getOptions(); + graph = new Graph(options, getDebug(options)); for (int i = 0; i < nodes.length; i++) { nodes[i] = graph.add(new TestNode()); } @@ -107,13 +110,6 @@ public class NodeMapTest { } } - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; - return assertionsEnabled; - } - @Test public void testNewGet() { /* @@ -123,7 +119,7 @@ public class NodeMapTest { TestNode newNode = graph.add(new TestNode()); try { map.get(newNode); - fail("expected " + (assertionsEnabled() ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName())); + fail("expected " + (Assertions.assertionsEnabled() ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName())); } catch (AssertionError ae) { // thrown when assertions are enabled } catch (ArrayIndexOutOfBoundsException e) { @@ -140,7 +136,7 @@ public class NodeMapTest { TestNode newNode = graph.add(new TestNode()); try { map.set(newNode, 1); - fail("expected " + (assertionsEnabled() ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName())); + fail("expected " + (Assertions.assertionsEnabled() ? AssertionError.class.getSimpleName() : ArrayIndexOutOfBoundsException.class.getSimpleName())); } catch (AssertionError ae) { // thrown when assertions are enabled } catch (ArrayIndexOutOfBoundsException e) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeUsagesTests.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeUsagesTests.java index 2f8f34f82b0..367b40dd076 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeUsagesTests.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeUsagesTests.java @@ -36,8 +36,9 @@ import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.options.OptionValues; -public class NodeUsagesTests { +public class NodeUsagesTests extends GraphTest { @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) static final class Def extends Node { @@ -66,7 +67,8 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsages() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -95,7 +97,8 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicateAll() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -124,7 +127,8 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicateNone() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -153,7 +157,8 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate1() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -184,7 +189,8 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate2() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -215,7 +221,8 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate0() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -246,7 +253,8 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate02() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -277,7 +285,8 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate023() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -311,7 +320,8 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate013() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -345,7 +355,8 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate203() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -379,7 +390,8 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate01() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); @@ -410,7 +422,8 @@ public class NodeUsagesTests { @Test public void testReplaceAtUsagesWithPredicate12() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); Def def0 = graph.add(new Def()); Def def1 = graph.add(new Def()); Use use0 = graph.add(new Use(def0, null, null)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeValidationChecksTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeValidationChecksTest.java index 18d822d34ec..f26fffb617c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeValidationChecksTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/NodeValidationChecksTest.java @@ -33,7 +33,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; -public class NodeValidationChecksTest { +public class NodeValidationChecksTest extends GraphTest { @NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN) static final class TestNode extends Node { @@ -51,7 +51,7 @@ public class NodeValidationChecksTest { @Test public void testInputNotAlive() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions(), getDebug()); TestNode node = new TestNode(null, null); try { graph.add(new TestNode(node, null)); @@ -64,7 +64,7 @@ public class NodeValidationChecksTest { @Test public void testSuccessorNotAlive() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions(), getDebug()); TestNode node = new TestNode(null, null); try { graph.add(new TestNode(null, node)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest.java index 269143bbe33..a397639127d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest.java @@ -33,14 +33,15 @@ import static org.junit.Assert.fail; import java.util.Iterator; import org.junit.Test; - +import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.graph.Graph; import org.graalvm.compiler.graph.IterableNodeType; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.options.OptionValues; -public class TypedNodeIteratorTest { +public class TypedNodeIteratorTest extends GraphTest { @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) static final class TestNode extends Node implements IterableNodeType, TestNodeInterface { @@ -61,16 +62,22 @@ public class TypedNodeIteratorTest { @Test public void singleNodeTest() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); graph.add(new TestNode("a")); assertTrue(graph.hasNode(TestNode.TYPE)); assertEquals("a", toString(graph.getNodes(TestNode.TYPE))); } + static OptionValues getOptions() { + return Graal.getRequiredCapability(OptionValues.class); + } + @Test public void deletingNodeTest() { TestNode testNode = new TestNode("a"); - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); graph.add(testNode); testNode.safeDelete(); assertEquals("", toString(graph.getNodes(TestNode.TYPE))); @@ -79,7 +86,8 @@ public class TypedNodeIteratorTest { @Test public void deleteAndAddTest() { TestNode testNode = new TestNode("b"); - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); graph.add(new TestNode("a")); graph.add(testNode); testNode.safeDelete(); @@ -90,7 +98,8 @@ public class TypedNodeIteratorTest { @Test public void iteratorBehaviorTest() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); graph.add(new TestNode("a")); Iterator iterator = graph.getNodes(TestNode.TYPE).iterator(); assertTrue(iterator.hasNext()); @@ -109,7 +118,8 @@ public class TypedNodeIteratorTest { @Test public void complicatedIterationTest() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); graph.add(new TestNode("a")); for (TestNode tn : graph.getNodes(TestNode.TYPE)) { String name = tn.getName(); @@ -148,7 +158,8 @@ public class TypedNodeIteratorTest { @Test public void addingNodeDuringIterationTest() { - Graph graph = new Graph(); + OptionValues options = getOptions(); + Graph graph = new Graph(options, getDebug(options)); graph.add(new TestNode("a")); StringBuilder sb = new StringBuilder(); int z = 0; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest2.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest2.java index c56b19c4b70..2321583dd7f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest2.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph.test/src/org/graalvm/compiler/graph/test/TypedNodeIteratorTest2.java @@ -36,7 +36,7 @@ import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; -public class TypedNodeIteratorTest2 { +public class TypedNodeIteratorTest2 extends GraphTest { @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) static class NodeA extends Node implements TestNodeInterface { @@ -99,7 +99,7 @@ public class TypedNodeIteratorTest2 { @Test public void simpleSubclassTest() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions(), getDebug()); graph.add(new NodeB("b")); graph.add(new NodeD("d")); @@ -109,7 +109,7 @@ public class TypedNodeIteratorTest2 { @Test public void addingNodeDuringIterationTest() { - Graph graph = new Graph(); + Graph graph = new Graph(getOptions(), getDebug()); graph.add(new NodeB("b1")); NodeD d1 = graph.add(new NodeD("d1")); StringBuilder sb = new StringBuilder(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/.checkstyle_checks.xml b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/.checkstyle_checks.xml index f18b015c883..85607d1b5e4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/.checkstyle_checks.xml +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/.checkstyle_checks.xml @@ -135,9 +135,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + - + + diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java index 42122975c5d..65ce0ff9f93 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java @@ -22,9 +22,10 @@ */ package org.graalvm.compiler.graph; -import java.util.Map; import java.util.function.Consumer; +import org.graalvm.util.UnmodifiableEconomicMap; + /** * This class is a container of a graph that needs to be readonly and optionally a lazily created * mutable copy of the graph. @@ -59,9 +60,11 @@ public final class CachedGraph { } @SuppressWarnings("unchecked") - public G getMutableCopy(Consumer> duplicationMapCallback) { + public G getMutableCopy(Consumer> duplicationMapCallback) { if (!hasMutableCopy()) { - mutableCopy = (G) readonlyCopy.copy(duplicationMapCallback); + // Sharing the debug context with the copy is safe since both graphs are + // only used in the current thread. + mutableCopy = (G) readonlyCopy.copy(duplicationMapCallback, readonlyCopy.getDebug()); } return mutableCopy; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/DefaultNodeCollectionsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/DefaultNodeCollectionsProvider.java deleted file mode 100644 index 70da681313f..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/DefaultNodeCollectionsProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.graph; - -import java.util.Collections; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.Set; - -import org.graalvm.compiler.api.collections.DefaultCollectionsProvider; - -/** - * A default implementation of {@link NodeCollectionsProvider} that creates standard JDK collection - * class objects. - */ -public class DefaultNodeCollectionsProvider extends DefaultCollectionsProvider implements NodeCollectionsProvider { - - @Override - public Set newNodeIdentitySet() { - return Collections.newSetFromMap(newNodeIdentityMap()); - } - - @Override - public Map newNodeIdentityMap() { - return new IdentityHashMap<>(); - } - - @Override - public Map newNodeIdentityMap(int expectedMaxSize) { - return new IdentityHashMap<>(expectedMaxSize); - } - - @Override - public Map newNodeIdentityMap(Map initFrom) { - return new IdentityHashMap<>(initFrom); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java index 4c36413e06c..0e7edffcec6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Edges.java @@ -71,11 +71,11 @@ public abstract class Edges extends Fields { return (NodeList) UNSAFE.getObject(node, offset); } - private static void putNodeUnsafe(Node node, long offset, Node value) { + public static void putNodeUnsafe(Node node, long offset, Node value) { UNSAFE.putObject(node, offset, value); } - private static void putNodeListUnsafe(Node node, long offset, NodeList value) { + public static void putNodeListUnsafe(Node node, long offset, NodeList value) { UNSAFE.putObject(node, offset, value); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java index 8e99606de1d..509f11841f6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -22,25 +22,28 @@ */ package org.graalvm.compiler.graph; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; + import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.Iterator; -import java.util.Map; import java.util.function.Consumer; -import org.graalvm.compiler.core.common.CollectionsFactory; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.Fingerprint; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.graph.Node.ValueNumberable; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; +import org.graalvm.util.UnmodifiableEconomicMap; /** * This class is a graph container, it contains the set of nodes that belong to this graph. @@ -49,13 +52,17 @@ public class Graph { public static class Options { @Option(help = "Verify graphs often during compilation when assertions are turned on", type = OptionType.Debug)// - public static final OptionValue VerifyGraalGraphs = new OptionValue<>(true); + public static final OptionKey VerifyGraalGraphs = new OptionKey<>(true); @Option(help = "Perform expensive verification of graph inputs, usages, successors and predecessors", type = OptionType.Debug)// - public static final OptionValue VerifyGraalGraphEdges = new OptionValue<>(false); + public static final OptionKey VerifyGraalGraphEdges = new OptionKey<>(false); @Option(help = "Graal graph compression is performed when percent of live nodes falls below this value", type = OptionType.Debug)// - public static final OptionValue GraphCompressionThreshold = new OptionValue<>(70); - @Option(help = "Use Unsafe to clone graph nodes thus avoiding copying fields that will be re-initialized anyway", type = OptionType.Debug)// - public static final OptionValue CloneNodesWithUnsafe = new OptionValue<>(true); + public static final OptionKey GraphCompressionThreshold = new OptionKey<>(70); + } + + private enum FreezeState { + Unfrozen, + TemporaryFreeze, + DeepFreeze } public final String name; @@ -109,51 +116,41 @@ public class Graph { * Used to global value number {@link ValueNumberable} {@linkplain NodeClass#isLeafNode() leaf} * nodes. */ - private final HashMap cachedLeafNodes = CollectionsFactory.newMap(); + private EconomicMap[] cachedLeafNodes; - /* - * Indicates that the graph should no longer be modified. Frozen graphs can be used my multiple - * threads so it's only safe to read them. - */ - private boolean isFrozen = false; - - /** - * Entry in {@link Graph#cachedLeafNodes}. - */ - private static final class CacheEntry { - - private final Node node; - - CacheEntry(Node node) { - assert node.getNodeClass().valueNumberable(); - assert node.getNodeClass().isLeafNode(); - this.node = node; - } + private static final Equivalence NODE_VALUE_COMPARE = new Equivalence() { @Override - public int hashCode() { - return node.getNodeClass().valueNumber(node); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { + public boolean equals(Object a, Object b) { + if (a == b) { return true; } - if (obj instanceof CacheEntry) { - CacheEntry other = (CacheEntry) obj; - if (other.node.getClass() == node.getClass()) { - return node.valueEquals(other.node); - } - } - return false; + + assert a.getClass() == b.getClass(); + return ((Node) a).valueEquals((Node) b); } @Override - public String toString() { - return node.toString(); + public int hashCode(Object k) { + return ((Node) k).getNodeClass().valueNumber((Node) k); } - } + }; + + /** + * Indicates that the graph should no longer be modified. Frozen graphs can be used by multiple + * threads so it's only safe to read them. + */ + private FreezeState freezeState = FreezeState.Unfrozen; + + /** + * The option values used while compiling this graph. + */ + private final OptionValues options; + + /** + * The {@link DebugContext} used while compiling this graph. + */ + private DebugContext debug; private class NodeSourcePositionScope implements DebugCloseable { private final NodeSourcePosition previous; @@ -163,6 +160,11 @@ public class Graph { currentNodeSourcePosition = sourcePosition; } + @Override + public DebugContext getDebug() { + return debug; + } + @Override public void close() { currentNodeSourcePosition = previous; @@ -225,8 +227,8 @@ public class Graph { /** * Creates an empty Graph with no name. */ - public Graph() { - this(null); + public Graph(OptionValues options, DebugContext debug) { + this(null, options, debug); } /** @@ -247,11 +249,15 @@ public class Graph { * * @param name the name of the graph, used for debugging purposes */ - public Graph(String name) { + public Graph(String name, OptionValues options, DebugContext debug) { nodes = new Node[INITIAL_NODES_SIZE]; iterableNodesFirst = new ArrayList<>(NodeClass.allocatedNodeIterabledIds()); iterableNodesLast = new ArrayList<>(NodeClass.allocatedNodeIterabledIds()); this.name = name; + this.options = options; + assert debug != null; + this.debug = debug; + if (isModificationCountsEnabled()) { nodeModCounts = new int[INITIAL_NODES_SIZE]; nodeUsageModCounts = new int[INITIAL_NODES_SIZE]; @@ -308,27 +314,37 @@ public class Graph { /** * Creates a copy of this graph. + * + * @param debugForCopy the debug context for the graph copy. This must not be the debug for this + * graph if this graph can be accessed from multiple threads (e.g., it's in a cache + * accessed by multiple threads). */ - public final Graph copy() { - return copy(name, null); + public final Graph copy(DebugContext debugForCopy) { + return copy(name, null, debugForCopy); } /** * Creates a copy of this graph. * * @param duplicationMapCallback consumer of the duplication map created during the copying + * @param debugForCopy the debug context for the graph copy. This must not be the debug for this + * graph if this graph can be accessed from multiple threads (e.g., it's in a cache + * accessed by multiple threads). */ - public final Graph copy(Consumer> duplicationMapCallback) { - return copy(name, duplicationMapCallback); + public final Graph copy(Consumer> duplicationMapCallback, DebugContext debugForCopy) { + return copy(name, duplicationMapCallback, debugForCopy); } /** * Creates a copy of this graph. * * @param newName the name of the copy, used for debugging purposes (can be null) + * @param debugForCopy the debug context for the graph copy. This must not be the debug for this + * graph if this graph can be accessed from multiple threads (e.g., it's in a cache + * accessed by multiple threads). */ - public final Graph copy(String newName) { - return copy(newName, null); + public final Graph copy(String newName, DebugContext debugForCopy) { + return copy(newName, null, debugForCopy); } /** @@ -336,16 +352,42 @@ public class Graph { * * @param newName the name of the copy, used for debugging purposes (can be null) * @param duplicationMapCallback consumer of the duplication map created during the copying + * @param debugForCopy the debug context for the graph copy. This must not be the debug for this + * graph if this graph can be accessed from multiple threads (e.g., it's in a cache + * accessed by multiple threads). */ - protected Graph copy(String newName, Consumer> duplicationMapCallback) { - Graph copy = new Graph(newName); - Map duplicates = copy.addDuplicates(getNodes(), this, this.getNodeCount(), (Map) null); + protected Graph copy(String newName, Consumer> duplicationMapCallback, DebugContext debugForCopy) { + Graph copy = new Graph(newName, options, debugForCopy); + UnmodifiableEconomicMap duplicates = copy.addDuplicates(getNodes(), this, this.getNodeCount(), (EconomicMap) null); if (duplicationMapCallback != null) { duplicationMapCallback.accept(duplicates); } return copy; } + public final OptionValues getOptions() { + return options; + } + + public DebugContext getDebug() { + return debug; + } + + /** + * Resets the {@link DebugContext} for this graph to a new value. This is useful when a graph is + * "handed over" from its creating thread to another thread. + * + * This must only be done when the current thread is no longer using the graph. This is in + * general impossible to test due to races and since metrics can be updated at any time. As + * such, this method only performs a weak sanity check that at least the current debug context + * does not have a nested scope open (the top level scope will always be open if scopes are + * enabled). + */ + public void resetDebug(DebugContext newDebug) { + assert newDebug == debug || !debug.inNestedScope() : String.format("Cannot reset the debug context for %s while it has the nested scope \"%s\" open", this, debug.getCurrentScopeName()); + this.debug = newDebug; + } + @Override public String toString() { return name == null ? super.toString() : "Graph " + name; @@ -404,22 +446,30 @@ public class Graph { public T addOrUnique(T node) { if (node.getNodeClass().valueNumberable()) { - return uniqueHelper(node, true); + return uniqueHelper(node); } return add(node); } - public T addWithoutUniqueWithInputs(T node) { - addInputs(node); - return addHelper(node); + public T maybeAddOrUnique(T node) { + if (node.isAlive()) { + return node; + } + return addOrUnique(node); } public T addOrUniqueWithInputs(T node) { - addInputs(node); - if (node.getNodeClass().valueNumberable()) { - return uniqueHelper(node, true); + if (node.isAlive()) { + assert node.graph() == this; + return node; + } else { + assert node.isUnregistered(); + addInputs(node); + if (node.getNodeClass().valueNumberable()) { + return uniqueHelper(node); + } + return add(node); } - return add(node); } private final class AddInputsFilter extends Node.EdgeVisitor { @@ -583,16 +633,16 @@ public class Graph { * @return a node similar to {@code node} if one exists, otherwise {@code node} */ public T unique(T node) { - return uniqueHelper(node, true); + return uniqueHelper(node); } - T uniqueHelper(T node, boolean addIfMissing) { + T uniqueHelper(T node) { assert node.getNodeClass().valueNumberable(); T other = this.findDuplicate(node); if (other != null) { return other; } else { - T result = addIfMissing ? addHelper(node) : node; + T result = addHelper(node); if (node.getNodeClass().isLeafNode()) { putNodeIntoCache(result); } @@ -600,21 +650,47 @@ public class Graph { } } + void removeNodeFromCache(Node node) { + assert node.graph() == this || node.graph() == null; + assert node.getNodeClass().valueNumberable(); + assert node.getNodeClass().isLeafNode() : node.getClass(); + + int leafId = node.getNodeClass().getLeafId(); + if (cachedLeafNodes != null && cachedLeafNodes.length > leafId && cachedLeafNodes[leafId] != null) { + cachedLeafNodes[leafId].removeKey(node); + } + } + + @SuppressWarnings({"unchecked", "rawtypes"}) void putNodeIntoCache(Node node) { assert node.graph() == this || node.graph() == null; assert node.getNodeClass().valueNumberable(); assert node.getNodeClass().isLeafNode() : node.getClass(); - CacheEntry entry = new CacheEntry(node); - cachedLeafNodes.put(entry, node); + + int leafId = node.getNodeClass().getLeafId(); + if (cachedLeafNodes == null || cachedLeafNodes.length <= leafId) { + EconomicMap[] newLeafNodes = new EconomicMap[leafId + 1]; + if (cachedLeafNodes != null) { + System.arraycopy(cachedLeafNodes, 0, newLeafNodes, 0, cachedLeafNodes.length); + } + cachedLeafNodes = newLeafNodes; + } + + if (cachedLeafNodes[leafId] == null) { + cachedLeafNodes[leafId] = EconomicMap.create(NODE_VALUE_COMPARE); + } + + cachedLeafNodes[leafId].put(node, node); } Node findNodeInCache(Node node) { - CacheEntry key = new CacheEntry(node); - Node result = cachedLeafNodes.get(key); - if (result != null && result.isDeleted()) { - cachedLeafNodes.remove(key); + int leafId = node.getNodeClass().getLeafId(); + if (cachedLeafNodes == null || cachedLeafNodes.length <= leafId || cachedLeafNodes[leafId] == null) { return null; } + + Node result = cachedLeafNodes[leafId].get(node); + assert result == null || result.isAlive() : result; return result; } @@ -763,7 +839,7 @@ public class Graph { } // Fully qualified annotation name is required to satisfy javac - @org.graalvm.compiler.nodeinfo.NodeInfo + @org.graalvm.compiler.nodeinfo.NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) static final class PlaceHolderNode extends Node { public static final NodeClass TYPE = NodeClass.create(PlaceHolderNode.class); @@ -774,27 +850,24 @@ public class Graph { } - static final Node PLACE_HOLDER = new PlaceHolderNode(); - - public static final int COMPRESSION_THRESHOLD = Options.GraphCompressionThreshold.getValue(); - - private static final DebugCounter GraphCompressions = Debug.counter("GraphCompressions"); + private static final CounterKey GraphCompressions = DebugContext.counter("GraphCompressions"); /** - * If the {@linkplain #COMPRESSION_THRESHOLD compression threshold} is met, the list of nodes is - * compressed such that all non-null entries precede all null entries while preserving the - * ordering between the nodes within the list. + * If the {@linkplain Options#GraphCompressionThreshold compression threshold} is met, the list + * of nodes is compressed such that all non-null entries precede all null entries while + * preserving the ordering between the nodes within the list. */ public boolean maybeCompress() { - if (Debug.isDumpEnabledForMethod() || Debug.isLogEnabledForMethod()) { + if (debug.isDumpEnabledForMethod() || debug.isLogEnabledForMethod()) { return false; } int liveNodeCount = getNodeCount(); int liveNodePercent = liveNodeCount * 100 / nodesSize; - if (COMPRESSION_THRESHOLD == 0 || liveNodePercent >= COMPRESSION_THRESHOLD) { + int compressionThreshold = Options.GraphCompressionThreshold.getValue(options); + if (compressionThreshold == 0 || liveNodePercent >= compressionThreshold) { return false; } - GraphCompressions.increment(); + GraphCompressions.increment(debug); int nextId = 0; for (int i = 0; nextId < liveNodeCount; i++) { Node n = nodes[i]; @@ -937,31 +1010,33 @@ public class Graph { assert !isFrozen(); assert node.id() == Node.INITIAL_ID; if (nodes.length == nodesSize) { - Node[] newNodes = new Node[(nodesSize * 2) + 1]; - System.arraycopy(nodes, 0, newNodes, 0, nodesSize); - nodes = newNodes; + grow(); } - int id = nodesSize; + int id = nodesSize++; nodes[id] = node; + node.id = id; if (currentNodeSourcePosition != null) { node.setNodeSourcePosition(currentNodeSourcePosition); - } else if (!seenNodeSourcePosition && node.getNodeSourcePosition() != null) { - seenNodeSourcePosition = true; } - nodesSize++; + seenNodeSourcePosition = seenNodeSourcePosition || node.getNodeSourcePosition() != null; updateNodeCaches(node); - node.id = id; if (nodeEventListener != null) { nodeEventListener.nodeAdded(node); } - if (!seenNodeSourcePosition && node.sourcePosition != null) { - seenNodeSourcePosition = true; - } - if (Fingerprint.ENABLED) { - Fingerprint.submit("%s: %s", NodeEvent.NODE_ADDED, node); - } + afterRegister(node); + } + + private void grow() { + Node[] newNodes = new Node[(nodesSize * 2) + 1]; + System.arraycopy(nodes, 0, newNodes, 0, nodesSize); + nodes = newNodes; + } + + @SuppressWarnings("unused") + protected void afterRegister(Node node) { + } @SuppressWarnings("unused") @@ -1003,7 +1078,10 @@ public class Graph { void unregister(Node node) { assert !isFrozen(); - assert !node.isDeleted() : "cannot delete a node twice! node=" + node; + assert !node.isDeleted() : node; + if (node.getNodeClass().isLeafNode() && node.getNodeClass().valueNumberable()) { + removeNodeFromCache(node); + } nodes[node.id] = null; nodesDeletedSinceLastCompression++; @@ -1011,7 +1089,7 @@ public class Graph { } public boolean verify() { - if (Options.VerifyGraalGraphs.getValue()) { + if (Options.VerifyGraalGraphs.getValue(options)) { for (Node node : getNodes()) { try { try { @@ -1043,7 +1121,7 @@ public class Graph { } /** - * Adds duplicates of the nodes in {@code nodes} to this graph. This will recreate any edges + * Adds duplicates of the nodes in {@code newNodes} to this graph. This will recreate any edges * between the duplicate nodes. The {@code replacement} map can be used to replace a node from * the source graph by a given node (which must already be in this graph). Edges between * duplicate and replacement nodes will also be recreated so care should be taken regarding the @@ -1053,7 +1131,7 @@ public class Graph { * @param replacementsMap the replacement map (can be null if no replacement is to be performed) * @return a map which associates the original nodes from {@code nodes} to their duplicates */ - public Map addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, Map replacementsMap) { + public UnmodifiableEconomicMap addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, EconomicMap replacementsMap) { DuplicationReplacement replacements; if (replacementsMap == null) { replacements = null; @@ -1070,9 +1148,9 @@ public class Graph { private static final class MapReplacement implements DuplicationReplacement { - private final Map map; + private final EconomicMap map; - MapReplacement(Map map) { + MapReplacement(EconomicMap map) { this.map = map; } @@ -1084,30 +1162,34 @@ public class Graph { } - private static final DebugTimer DuplicateGraph = Debug.timer("DuplicateGraph"); + private static final TimerKey DuplicateGraph = DebugContext.timer("DuplicateGraph"); @SuppressWarnings({"all", "try"}) - public Map addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, DuplicationReplacement replacements) { - try (DebugCloseable s = DuplicateGraph.start()) { + public EconomicMap addDuplicates(Iterable newNodes, final Graph oldGraph, int estimatedNodeCount, DuplicationReplacement replacements) { + try (DebugCloseable s = DuplicateGraph.start(getDebug())) { return NodeClass.addGraphDuplicate(this, oldGraph, estimatedNodeCount, newNodes, replacements); } } - /** - * Reverses the usage orders of all nodes. This is used for debugging to make sure an unorthodox - * usage order does not trigger bugs in the compiler. - */ - public void reverseUsageOrder() { - for (Node n : getNodes()) { - n.reverseUsageOrder(); - } - } - public boolean isFrozen() { - return isFrozen; + return freezeState != FreezeState.Unfrozen; } public void freeze() { - this.isFrozen = true; + this.freezeState = FreezeState.DeepFreeze; + } + + public void temporaryFreeze() { + if (this.freezeState == FreezeState.DeepFreeze) { + throw new GraalError("Graph was permanetly frozen."); + } + this.freezeState = FreezeState.TemporaryFreeze; + } + + public void unfreeze() { + if (this.freezeState == FreezeState.DeepFreeze) { + throw new GraalError("Graph was permanetly frozen."); + } + this.freezeState = FreezeState.Unfrozen; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java index 14ebbd82f08..7c886d37cb0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java @@ -29,24 +29,21 @@ import static org.graalvm.compiler.graph.UnsafeAccess.UNSAFE; import java.lang.annotation.ElementType; import java.lang.annotation.RetentionPolicy; -import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.Formattable; import java.util.FormattableFlags; import java.util.Formatter; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; import java.util.function.Predicate; -import org.graalvm.compiler.core.common.CollectionsFactory; import org.graalvm.compiler.core.common.Fields; +import org.graalvm.compiler.core.common.type.AbstractPointerStamp; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.Fingerprint; -import org.graalvm.compiler.graph.Graph.NodeEvent; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Graph.NodeEventListener; import org.graalvm.compiler.graph.Graph.Options; import org.graalvm.compiler.graph.iterators.NodeIterable; @@ -54,8 +51,11 @@ import org.graalvm.compiler.graph.iterators.NodePredicate; import org.graalvm.compiler.graph.spi.Simplifiable; import org.graalvm.compiler.graph.spi.SimplifierTool; import org.graalvm.compiler.nodeinfo.InputType; +import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodeinfo.Verbosity; +import org.graalvm.compiler.options.OptionValues; import sun.misc.Unsafe; @@ -71,21 +71,6 @@ import sun.misc.Unsafe; *

      * Nodes which are be value numberable should implement the {@link ValueNumberable} interface. * - *

      Replay Compilation

      - * - * To enable deterministic replay compilation, node sets and node maps should be instantiated with - * the following methods: - *
        - *
      • {@link #newSet()}
      • - *
      • {@link #newSet(Collection)}
      • - *
      • {@link #newMap()}
      • - *
      • {@link #newMap(int)}
      • - *
      • {@link #newMap(Map)}
      • - *
      • {@link #newIdentityMap()}
      • - *
      • {@link #newIdentityMap(int)}
      • - *
      • {@link #newIdentityMap(Map)}
      • - *
      - * *

      Assertions and Verification

      * * The Node class supplies the {@link #assertTrue(boolean, String, Object...)} and @@ -98,7 +83,7 @@ import sun.misc.Unsafe; public abstract class Node implements Cloneable, Formattable, NodeInterface { public static final NodeClass TYPE = null; - public static final boolean USE_UNSAFE_TO_CLONE = Graph.Options.CloneNodesWithUnsafe.getValue(); + public static final boolean USE_UNSAFE_TO_CLONE = true; static final int DELETED_ID_START = -1000000000; static final int INITIAL_ID = -1; @@ -149,7 +134,9 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { * Denotes an injected parameter in a {@linkplain NodeIntrinsic node intrinsic} constructor. If * the constructor is called as part of node intrinsification, the node intrinsifier will inject * an argument for the annotated parameter. Injected parameters must precede all non-injected - * parameters in a constructor. + * parameters in a constructor. If the type of the annotated parameter is {@link Stamp}, the + * {@linkplain Stamp#javaType type} of the injected stamp is the return type of the annotated + * method (which cannot be {@code void}). */ @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) @java.lang.annotation.Target(ElementType.PARAMETER) @@ -158,40 +145,45 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { /** * Annotates a method that can be replaced by a compiler intrinsic. A (resolved) call to the - * annotated method can be replaced with an instance of the node class denoted by - * {@link #value()}. For this reason, the signature of the annotated method must match the - * signature (excluding a prefix of {@linkplain InjectedNodeParameter injected} parameters) of a - * constructor in the node class. + * annotated method will be processed by a generated {@code InvocationPlugin} that calls either + * a factory method or a constructor corresponding with the annotated method. *

      - * If the node class has a static method {@code intrinsify} with a matching signature plus a - * {@code GraphBuilderContext} as first argument, this method is called instead of creating the - * node. + * A factory method corresponding to an annotated method is a static method named + * {@code intrinsify} defined in the class denoted by {@link #value()}. In order, its signature + * is as follows: + *

        + *
      1. A {@code GraphBuilderContext} parameter.
      2. + *
      3. A {@code ResolvedJavaMethod} parameter.
      4. + *
      5. A sequence of zero or more {@linkplain InjectedNodeParameter injected} parameters.
      6. + *
      7. Remaining parameters that match the declared parameters of the annotated method.
      8. + *
      + * A constructor corresponding to an annotated method is defined in the class denoted by + * {@link #value()}. In order, its signature is as follows: + *
        + *
      1. A sequence of zero or more {@linkplain InjectedNodeParameter injected} parameters.
      2. + *
      3. Remaining parameters that match the declared parameters of the annotated method.
      4. + *
      + * There must be exactly one such factory method or constructor corresponding to a + * {@link NodeIntrinsic} annotated method. */ @java.lang.annotation.Retention(RetentionPolicy.RUNTIME) @java.lang.annotation.Target(ElementType.METHOD) public static @interface NodeIntrinsic { /** - * Gets the {@link Node} subclass instantiated when intrinsifying a call to the annotated - * method. If not specified, then the class in which the annotated method is declared is - * used (and is assumed to be a {@link Node} subclass). + * The class declaring the factory method or {@link Node} subclass declaring the constructor + * used to intrinsify a call to the annotated method. The default value is the class in + * which the annotated method is declared. */ Class value() default NodeIntrinsic.class; /** - * Determines if the stamp of the instantiated intrinsic node has its stamp set from the - * return type of the annotated method. - *

      - * When it is set to true, the stamp that is passed in to the constructor of ValueNode is - * ignored and can therefore safely be {@code null}. + * If {@code true}, the factory method or constructor selected by the annotation must have + * an {@linkplain InjectedNodeParameter injected} {@link Stamp} parameter. Calling + * {@link AbstractPointerStamp#nonNull()} on the injected stamp is guaranteed to return + * {@code true}. */ - boolean setStampFromReturnType() default false; - - /** - * Determines if the stamp of the instantiated intrinsic node is guaranteed to be non-null. - * Generally used in conjunction with {@link #setStampFromReturnType()}. - */ - boolean returnStampIsNonNull() default false; + boolean injectedStampIsNonNull() default false; } /** @@ -257,56 +249,6 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { return this; } - /** - * @see CollectionsFactory#newSet() - */ - public static Set newSet() { - return CollectionsFactory.newSet(); - } - - /** - * @see #newSet() - */ - public static Set newSet(Collection c) { - return CollectionsFactory.newSet(c); - } - - public static Map newMap() { - // Node.equals() and Node.hashCode() are final and are implemented - // purely in terms of identity so HashMap and IdentityHashMap with - // Node's as keys will behave the same. We choose to use the latter - // due to its lighter memory footprint. - return newIdentityMap(); - } - - public static Map newMap(Map m) { - // Node.equals() and Node.hashCode() are final and are implemented - // purely in terms of identity so HashMap and IdentityHashMap with - // Node's as keys will behave the same. We choose to use the latter - // due to its lighter memory footprint. - return newIdentityMap(m); - } - - public static Map newMap(int expectedMaxSize) { - // Node.equals() and Node.hashCode() are final and are implemented - // purely in terms of identity so HashMap and IdentityHashMap with - // Node's as keys will behave the same. We choose to use the latter - // due to its lighter memory footprint. - return newIdentityMap(expectedMaxSize); - } - - public static Map newIdentityMap() { - return CollectionsFactory.newIdentityMap(); - } - - public static Map newIdentityMap(Map m) { - return CollectionsFactory.newIdentityMap(m); - } - - public static Map newIdentityMap(int expectedMaxSize) { - return CollectionsFactory.newIdentityMap(expectedMaxSize); - } - /** * Gets the graph context of this node. */ @@ -314,6 +256,20 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { return graph; } + /** + * Gets the option values associated with this node's graph. + */ + public final OptionValues getOptions() { + return graph == null ? null : graph.getOptions(); + } + + /** + * Gets the debug context associated with this node's graph. + */ + public final DebugContext getDebug() { + return graph.getDebug(); + } + /** * Returns an {@link NodeIterable iterable} which can be used to traverse all non-null input * edges of this node. @@ -365,7 +321,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { * @return an {@link NodeIterable iterable} for all non-null successor edges. */ public NodeIterable successors() { - assert !this.isDeleted(); + assert !this.isDeleted() : this; return nodeClass.getSuccessorIterable(this); } @@ -389,7 +345,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { if (usage1 == null) { return 1; } - return 2 + extraUsagesCount; + return INLINE_USAGE_COUNT + extraUsagesCount; } /** @@ -413,15 +369,18 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { return this.usage0 != null; } - void reverseUsageOrder() { - List snapshot = this.usages().snapshot(); - for (Node n : snapshot) { - this.removeUsage(n); - } - Collections.reverse(snapshot); - for (Node n : snapshot) { - this.addUsage(n); - } + /** + * Checks whether this node has more than one usages. + */ + public final boolean hasMoreThanOneUsage() { + return this.usage1 != null; + } + + /** + * Checks whether this node has exactly one usgae. + */ + public final boolean hasExactlyOneUsage() { + return hasUsages() && !hasMoreThanOneUsage(); } /** @@ -449,30 +408,45 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { } private void movUsageFromEndTo(int destIndex) { - int lastIndex = this.getUsageCount() - 1; - if (destIndex == 0) { - if (lastIndex == 0) { - usage0 = null; - return; - } else if (lastIndex == 1) { - usage0 = usage1; - usage1 = null; - return; - } else { - usage0 = extraUsages[lastIndex - INLINE_USAGE_COUNT]; - } + if (destIndex >= INLINE_USAGE_COUNT) { + movUsageFromEndToExtraUsages(destIndex - INLINE_USAGE_COUNT); } else if (destIndex == 1) { - if (lastIndex == 1) { - usage1 = null; - return; - } - usage1 = extraUsages[lastIndex - INLINE_USAGE_COUNT]; + movUsageFromEndToIndexOne(); } else { - Node n = extraUsages[lastIndex - INLINE_USAGE_COUNT]; - extraUsages[destIndex - INLINE_USAGE_COUNT] = n; + assert destIndex == 0; + movUsageFromEndToIndexZero(); } - extraUsages[lastIndex - INLINE_USAGE_COUNT] = null; + } + + private void movUsageFromEndToExtraUsages(int destExtraIndex) { this.extraUsagesCount--; + Node n = extraUsages[extraUsagesCount]; + extraUsages[destExtraIndex] = n; + extraUsages[extraUsagesCount] = null; + } + + private void movUsageFromEndToIndexZero() { + if (extraUsagesCount > 0) { + this.extraUsagesCount--; + usage0 = extraUsages[extraUsagesCount]; + extraUsages[extraUsagesCount] = null; + } else if (usage1 != null) { + usage0 = usage1; + usage1 = null; + } else { + usage0 = null; + } + } + + private void movUsageFromEndToIndexOne() { + if (extraUsagesCount > 0) { + this.extraUsagesCount--; + usage1 = extraUsages[extraUsagesCount]; + extraUsages[extraUsagesCount] = null; + } else { + assert usage1 != null; + usage1 = null; + } } /** @@ -483,20 +457,21 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { */ public boolean removeUsage(Node node) { assert node != null; - // It is critical that this method maintains the invariant that - // the usage list has no null element preceding a non-null element + // For large graphs, usage removal is performance critical. + // Furthermore, it is critical that this method maintains the invariant that the usage list + // has no null element preceding a non-null element. incUsageModCount(); if (usage0 == node) { - this.movUsageFromEndTo(0); + movUsageFromEndToIndexZero(); return true; } if (usage1 == node) { - this.movUsageFromEndTo(1); + movUsageFromEndToIndexOne(); return true; } for (int i = this.extraUsagesCount - 1; i >= 0; i--) { if (extraUsages[i] == node) { - this.movUsageFromEndTo(i + INLINE_USAGE_COUNT); + movUsageFromEndToExtraUsages(i); return true; } } @@ -533,14 +508,18 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { } } - public boolean isDeleted() { + public final boolean isDeleted() { return id <= DELETED_ID_START; } - public boolean isAlive() { + public final boolean isAlive() { return id >= ALIVE_ID_START; } + public final boolean isUnregistered() { + return id == INITIAL_ID; + } + /** * Updates the usages sets of the given nodes after an input slot is changed from * {@code oldInput} to {@code newInput} by removing this node from {@code oldInput}'s usages and @@ -591,8 +570,9 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { assert assertTrue(id == INITIAL_ID, "unexpected id: %d", id); this.graph = newGraph; newGraph.register(this); - this.getNodeClass().registerAtInputsAsUsage(this); - this.getNodeClass().registerAtSuccessorsAsPredecessor(this); + NodeClass nc = nodeClass; + nc.registerAtInputsAsUsage(this); + nc.registerAtSuccessorsAsPredecessor(this); } /** @@ -634,15 +614,23 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { } private boolean checkReplaceWith(Node other) { - assert assertTrue(graph == null || !graph.isFrozen(), "cannot modify frozen graph"); - assert assertFalse(other == this, "cannot replace a node with itself"); - assert assertFalse(isDeleted(), "cannot replace deleted node"); - assert assertTrue(other == null || !other.isDeleted(), "cannot replace with deleted node %s", other); + if (graph != null && graph.isFrozen()) { + fail("cannot modify frozen graph"); + } + if (other == this) { + fail("cannot replace a node with itself"); + } + if (isDeleted()) { + fail("cannot replace deleted node"); + } + if (other != null && other.isDeleted()) { + fail("cannot replace with deleted node %s", other); + } return true; } public final void replaceAtUsages(Node other) { - replaceAtUsages(other, null, null); + replaceAtAllUsages(other, (Node) null); } public final void replaceAtUsages(Node other, Predicate filter) { @@ -660,22 +648,62 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { } protected void replaceAtUsages(Node other, Predicate filter, Node toBeDeleted) { - assert checkReplaceWith(other); + if (filter == null) { + replaceAtAllUsages(other, toBeDeleted); + } else { + replaceAtMatchingUsages(other, filter, toBeDeleted); + } + } + + protected void replaceAtAllUsages(Node other, Node toBeDeleted) { + checkReplaceWith(other); + if (usage0 == null) { + return; + } + replaceAtUsage(other, toBeDeleted, usage0); + usage0 = null; + + if (usage1 == null) { + return; + } + replaceAtUsage(other, toBeDeleted, usage1); + usage1 = null; + + if (extraUsagesCount <= 0) { + return; + } + for (int i = 0; i < extraUsagesCount; i++) { + Node usage = extraUsages[i]; + replaceAtUsage(other, toBeDeleted, usage); + } + this.extraUsages = NO_NODES; + this.extraUsagesCount = 0; + } + + private void replaceAtUsage(Node other, Node toBeDeleted, Node usage) { + boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); + assert assertTrue(result, "not found in inputs, usage: %s", usage); + /* + * Don't notify for nodes which are about to be deleted. + */ + if (toBeDeleted == null || usage != toBeDeleted) { + maybeNotifyInputChanged(usage); + } + if (other != null) { + other.addUsage(usage); + } + } + + private void replaceAtMatchingUsages(Node other, Predicate filter, Node toBeDeleted) { + if (filter == null) { + fail("filter cannot be null"); + } + checkReplaceWith(other); int i = 0; while (i < this.getUsageCount()) { Node usage = this.getUsageAt(i); - if (filter == null || filter.test(usage)) { - boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); - assert assertTrue(result, "not found in inputs, usage: %s", usage); - /* - * Don't notify for nodes which are about to be deleted. - */ - if (toBeDeleted == null || usage != toBeDeleted) { - maybeNotifyInputChanged(usage); - } - if (other != null) { - other.addUsage(usage); - } + if (filter.test(usage)) { + replaceAtUsage(other, toBeDeleted, usage); this.movUsageFromEndTo(i); } else { ++i; @@ -694,26 +722,12 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { } public void replaceAtMatchingUsages(Node other, NodePredicate usagePredicate) { - assert checkReplaceWith(other); - int index = 0; - while (index < this.getUsageCount()) { - Node usage = getUsageAt(index); - if (usagePredicate.apply(usage)) { - boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other); - assert assertTrue(result, "not found in inputs, usage: %s", usage); - if (other != null) { - maybeNotifyInputChanged(usage); - other.addUsage(usage); - } - this.movUsageFromEndTo(index); - } else { - index++; - } - } + checkReplaceWith(other); + replaceAtMatchingUsages(other, usagePredicate, null); } public void replaceAtUsages(InputType type, Node other) { - assert checkReplaceWith(other); + checkReplaceWith(other); for (Node usage : usages().snapshot()) { for (Position pos : usage.inputPositions()) { if (pos.getInputType() == type && pos.get(usage) == this) { @@ -730,9 +744,6 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { if (listener != null) { listener.inputChanged(node); } - if (Fingerprint.ENABLED) { - Fingerprint.submit("%s: %s", NodeEvent.INPUT_CHANGED, node); - } } } @@ -743,25 +754,27 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { if (listener != null && node.isAlive()) { listener.usagesDroppedToZero(node); } - if (Fingerprint.ENABLED) { - Fingerprint.submit("%s: %s", NodeEvent.ZERO_USAGES, node); - } } } public void replaceAtPredecessor(Node other) { - assert checkReplaceWith(other); + checkReplaceWith(other); if (predecessor != null) { - boolean result = predecessor.getNodeClass().replaceFirstSuccessor(predecessor, this, other); - assert assertTrue(result, "not found in successors, predecessor: %s", predecessor); + if (!predecessor.getNodeClass().replaceFirstSuccessor(predecessor, this, other)) { + fail("not found in successors, predecessor: %s", predecessor); + } predecessor.updatePredecessor(this, other); } } public void replaceAndDelete(Node other) { - assert checkReplaceWith(other); - assert other != null; - replaceAtUsages(other); + checkReplaceWith(other); + if (other == null) { + fail("cannot replace with null"); + } + if (this.hasUsages()) { + replaceAtUsages(other); + } replaceAtPredecessor(other); this.safeDelete(); } @@ -852,12 +865,8 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { if (edgesToCopy.contains(type)) { getNodeClass().getEdges(type).copy(this, newNode); } else { - if (USE_UNSAFE_TO_CLONE) { - // The direct edges are already null - getNodeClass().getEdges(type).initializeLists(newNode, this); - } else { - getNodeClass().getEdges(type).clear(newNode); - } + // The direct edges are already null + getNodeClass().getEdges(type).initializeLists(newNode, this); } } @@ -891,22 +900,11 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { Node newNode = null; try { - if (USE_UNSAFE_TO_CLONE) { - newNode = (Node) UNSAFE.allocateInstance(getClass()); - newNode.nodeClass = nodeClassTmp; - nodeClassTmp.getData().copy(this, newNode); - copyOrClearEdgesForClone(newNode, Inputs, edgesToCopy); - copyOrClearEdgesForClone(newNode, Successors, edgesToCopy); - } else { - newNode = (Node) this.clone(); - newNode.typeCacheNext = null; - newNode.usage0 = null; - newNode.usage1 = null; - newNode.predecessor = null; - newNode.extraUsagesCount = 0; - copyOrClearEdgesForClone(newNode, Inputs, edgesToCopy); - copyOrClearEdgesForClone(newNode, Successors, edgesToCopy); - } + newNode = (Node) UNSAFE.allocateInstance(getClass()); + newNode.nodeClass = nodeClassTmp; + nodeClassTmp.getData().copy(this, newNode); + copyOrClearEdgesForClone(newNode, Inputs, edgesToCopy); + copyOrClearEdgesForClone(newNode, Successors, edgesToCopy); } catch (Exception e) { throw new GraalGraphError(e).addContext(this); } @@ -936,7 +934,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { if (input == null) { assertTrue(pos.isInputOptional(), "non-optional input %s cannot be null in %s (fix nullness or use @OptionalInput)", pos, this); } else { - assertFalse(input.isDeleted(), "input was deleted"); + assertFalse(input.isDeleted(), "input was deleted %s", input); assertTrue(input.isAlive(), "input is not alive yet, i.e., it was not yet added to the graph"); assertTrue(pos.getInputType() == InputType.Unchecked || input.isAllowedUsageType(pos.getInputType()), "invalid usage type %s %s", input, pos.getInputType()); } @@ -948,7 +946,7 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id); assertTrue(graph() != null, "null graph"); verifyInputs(); - if (Options.VerifyGraalGraphEdges.getValue()) { + if (Options.VerifyGraalGraphEdges.getValue(getOptions())) { verifyEdges(); } return true; @@ -1028,20 +1026,23 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { } /** - * Nodes always use an {@linkplain System#identityHashCode(Object) identity} hash code. + * Nodes using their {@link #id} as the hash code. This works very well when nodes of the same + * graph are stored in sets. It can give bad behavior when storing nodes of different graphs in + * the same set. */ @Override public final int hashCode() { - return System.identityHashCode(this); + assert !this.isUnregistered() : "node not yet constructed"; + if (this.isDeleted()) { + return -id + DELETED_ID_START; + } + return id; } /** - * Equality tests must rely solely on identity. + * Do not overwrite the equality test of a node in subclasses. Equality tests must rely solely + * on identity. */ - @Override - public final boolean equals(Object obj) { - return super.equals(obj); - } /** * Provides a {@link Map} of properties of this node for use in debugging (e.g., to view in the @@ -1187,4 +1188,13 @@ public abstract class Node implements Cloneable, Formattable, NodeInterface { public final void pushInputs(NodeStack stack) { getNodeClass().pushInputs(this, stack); } + + public NodeSize estimatedNodeSize() { + return nodeClass.size(); + } + + public NodeCycles estimatedNodeCycles() { + return nodeClass.cycles(); + } + } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java index b8333e3d9f9..6f27c243b92 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeBitMap.java @@ -154,7 +154,7 @@ public final class NodeBitMap implements NodeIterable { if (bits.length < other.bits.length) { bits = Arrays.copyOf(bits, other.bits.length); } - for (int i = 0; i < bits.length; i++) { + for (int i = 0; i < Math.min(bits.length, other.bits.length); i++) { bits[i] |= other.bits[i]; } } @@ -181,44 +181,47 @@ public final class NodeBitMap implements NodeIterable { } } - private static class MarkedNodeIterator implements Iterator { + protected int nextMarkedNodeId(int fromNodeId) { + assert fromNodeId >= 0; + int wordIndex = fromNodeId >> SHIFT; + int wordsInUse = bits.length; + if (wordIndex < wordsInUse) { + long word = bits[wordIndex] & (0xFFFFFFFFFFFFFFFFL << fromNodeId); + while (true) { + if (word != 0) { + return wordIndex * Long.SIZE + Long.numberOfTrailingZeros(word); + } + if (++wordIndex == wordsInUse) { + break; + } + word = bits[wordIndex]; + } + } + return -2; + } - private final NodeBitMap visited; - private Iterator nodes; - private Node nextNode; + private class MarkedNodeIterator implements Iterator { + private int nextNodeId; - MarkedNodeIterator(NodeBitMap visited, Iterator nodes) { - this.visited = visited; - this.nodes = nodes; + MarkedNodeIterator() { + nextNodeId = -1; forward(); } private void forward() { - do { - if (!nodes.hasNext()) { - nextNode = null; - return; - } - nextNode = nodes.next(); - if (visited.isNew(nextNode)) { - nextNode = null; - return; - } - } while (!visited.isMarked(nextNode)); + nextNodeId = NodeBitMap.this.nextMarkedNodeId(nextNodeId + 1); } @Override public boolean hasNext() { - return nextNode != null; + return nextNodeId >= 0; } @Override public Node next() { - try { - return nextNode; - } finally { - forward(); - } + Node result = graph.getNode(nextNodeId); + forward(); + return result; } @Override @@ -230,7 +233,7 @@ public final class NodeBitMap implements NodeIterable { @Override public Iterator iterator() { - return new MarkedNodeIterator(NodeBitMap.this, graph().getNodes().iterator()); + return new MarkedNodeIterator(); } public NodeBitMap copy() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java index b802b321e79..00a6487fb7c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java @@ -28,7 +28,6 @@ import static org.graalvm.compiler.graph.Edges.translateInto; import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled; import static org.graalvm.compiler.graph.InputEdges.translateInto; import static org.graalvm.compiler.graph.Node.WithAllEdges; -import static org.graalvm.compiler.graph.Node.newIdentityMap; import static org.graalvm.compiler.graph.UnsafeAccess.UNSAFE; import java.lang.annotation.Annotation; @@ -39,7 +38,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; import java.util.Iterator; -import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; @@ -47,12 +45,11 @@ import java.util.concurrent.atomic.AtomicInteger; import org.graalvm.compiler.core.common.FieldIntrospection; import org.graalvm.compiler.core.common.Fields; import org.graalvm.compiler.core.common.FieldsScanner; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugCounter; -import org.graalvm.compiler.debug.DebugTimer; -import org.graalvm.compiler.debug.Fingerprint; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.TimerKey; import org.graalvm.compiler.graph.Edges.Type; import org.graalvm.compiler.graph.Graph.DuplicationReplacement; import org.graalvm.compiler.graph.Node.EdgeVisitor; @@ -68,9 +65,8 @@ import org.graalvm.compiler.nodeinfo.NodeCycles; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodeinfo.Verbosity; -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; /** * Metadata for every {@link Node} type. The metadata includes: @@ -82,21 +78,14 @@ import org.graalvm.compiler.options.StableOptionValue; */ public final class NodeClass extends FieldIntrospection { - public static class Options { - // @formatter:off - @Option(help = "Verifies that receivers of NodeInfo#size() and NodeInfo#cycles() do not have UNSET values.") - public static final OptionValue VerifyNodeCostOnAccess = new StableOptionValue<>(false); - // @formatter:on - } - // Timers for creation of a NodeClass instance - private static final DebugTimer Init_FieldScanning = Debug.timer("NodeClass.Init.FieldScanning"); - private static final DebugTimer Init_FieldScanningInner = Debug.timer("NodeClass.Init.FieldScanning.Inner"); - private static final DebugTimer Init_AnnotationParsing = Debug.timer("NodeClass.Init.AnnotationParsing"); - private static final DebugTimer Init_Edges = Debug.timer("NodeClass.Init.Edges"); - private static final DebugTimer Init_Data = Debug.timer("NodeClass.Init.Data"); - private static final DebugTimer Init_AllowedUsages = Debug.timer("NodeClass.Init.AllowedUsages"); - private static final DebugTimer Init_IterableIds = Debug.timer("NodeClass.Init.IterableIds"); + private static final TimerKey Init_FieldScanning = DebugContext.timer("NodeClass.Init.FieldScanning"); + private static final TimerKey Init_FieldScanningInner = DebugContext.timer("NodeClass.Init.FieldScanning.Inner"); + private static final TimerKey Init_AnnotationParsing = DebugContext.timer("NodeClass.Init.AnnotationParsing"); + private static final TimerKey Init_Edges = DebugContext.timer("NodeClass.Init.Edges"); + private static final TimerKey Init_Data = DebugContext.timer("NodeClass.Init.Data"); + private static final TimerKey Init_AllowedUsages = DebugContext.timer("NodeClass.Init.AllowedUsages"); + private static final TimerKey Init_IterableIds = DebugContext.timer("NodeClass.Init.IterableIds"); public static final long MAX_EDGES = 8; public static final long MAX_LIST_EDGES = 6; @@ -105,8 +94,8 @@ public final class NodeClass extends FieldIntrospection { public static final long NEXT_EDGE = 0x08; @SuppressWarnings("try") - private static T getAnnotationTimed(AnnotatedElement e, Class annotationClass) { - try (DebugCloseable s = Init_AnnotationParsing.start()) { + private static T getAnnotationTimed(AnnotatedElement e, Class annotationClass, DebugContext debug) { + try (DebugCloseable s = Init_AnnotationParsing.start(debug)) { return e.getAnnotation(annotationClass); } } @@ -140,6 +129,7 @@ public final class NodeClass extends FieldIntrospection { private static final Class SUCCESSOR_LIST_CLASS = NodeSuccessorList.class; private static AtomicInteger nextIterableId = new AtomicInteger(); + private static AtomicInteger nextLeafId = new AtomicInteger(); private final InputEdges inputs; private final SuccessorEdges successors; @@ -154,8 +144,7 @@ public final class NodeClass extends FieldIntrospection { private final long inputsIteration; private final long successorIteration; - private static final DebugCounter ITERABLE_NODE_TYPES = Debug.counter("IterableNodeTypes"); - private final DebugCounter nodeIterableCount; + private static final CounterKey ITERABLE_NODE_TYPES = DebugContext.counter("IterableNodeTypes"); /** * Determines if this node type implements {@link Canonicalizable}. @@ -173,6 +162,8 @@ public final class NodeClass extends FieldIntrospection { private final boolean isSimplifiable; private final boolean isLeafNode; + private final int leafId; + public NodeClass(Class clazz, NodeClass superNodeClass) { this(clazz, superNodeClass, new FieldsScanner.DefaultCalcOffset(), null, 0); } @@ -180,6 +171,7 @@ public final class NodeClass extends FieldIntrospection { @SuppressWarnings("try") public NodeClass(Class clazz, NodeClass superNodeClass, FieldsScanner.CalcOffset calcOffset, int[] presetIterableIds, int presetIterableId) { super(clazz); + DebugContext debug = DebugContext.forCurrentThread(); this.superNodeClass = superNodeClass; assert NODE_CLASS.isAssignableFrom(clazz); @@ -191,31 +183,42 @@ public final class NodeClass extends FieldIntrospection { this.isSimplifiable = Simplifiable.class.isAssignableFrom(clazz); - NodeFieldsScanner fs = new NodeFieldsScanner(calcOffset, superNodeClass); - try (DebugCloseable t = Init_FieldScanning.start()) { + NodeFieldsScanner fs = new NodeFieldsScanner(calcOffset, superNodeClass, debug); + try (DebugCloseable t = Init_FieldScanning.start(debug)) { fs.scan(clazz, clazz.getSuperclass(), false); } - try (DebugCloseable t1 = Init_Edges.start()) { + try (DebugCloseable t1 = Init_Edges.start(debug)) { successors = new SuccessorEdges(fs.directSuccessors, fs.successors); successorIteration = computeIterationMask(successors.type(), successors.getDirectCount(), successors.getOffsets()); inputs = new InputEdges(fs.directInputs, fs.inputs); inputsIteration = computeIterationMask(inputs.type(), inputs.getDirectCount(), inputs.getOffsets()); } - try (DebugCloseable t1 = Init_Data.start()) { + try (DebugCloseable t1 = Init_Data.start(debug)) { data = new Fields(fs.data); } isLeafNode = inputs.getCount() + successors.getCount() == 0; + if (isLeafNode) { + this.leafId = nextLeafId.getAndIncrement(); + } else { + this.leafId = -1; + } canGVN = Node.ValueNumberable.class.isAssignableFrom(clazz); startGVNNumber = clazz.getName().hashCode(); - NodeInfo info = getAnnotationTimed(clazz, NodeInfo.class); + NodeInfo info = getAnnotationTimed(clazz, NodeInfo.class, debug); assert info != null : "Missing NodeInfo annotation on " + clazz; - this.nameTemplate = info.nameTemplate(); + if (!info.nameTemplate().isEmpty()) { + this.nameTemplate = info.nameTemplate(); + } else if (!info.shortName().isEmpty()) { + this.nameTemplate = info.shortName(); + } else { + this.nameTemplate = ""; + } - try (DebugCloseable t1 = Init_AllowedUsages.start()) { + try (DebugCloseable t1 = Init_AllowedUsages.start(debug)) { allowedUsageTypes = superNodeClass == null ? EnumSet.noneOf(InputType.class) : superNodeClass.allowedUsageTypes.clone(); allowedUsageTypes.addAll(Arrays.asList(info.allowedUsageTypes())); } @@ -224,8 +227,8 @@ public final class NodeClass extends FieldIntrospection { this.iterableIds = presetIterableIds; this.iterableId = presetIterableId; } else if (IterableNodeType.class.isAssignableFrom(clazz)) { - ITERABLE_NODE_TYPES.increment(); - try (DebugCloseable t1 = Init_IterableIds.start()) { + ITERABLE_NODE_TYPES.increment(debug); + try (DebugCloseable t1 = Init_IterableIds.start(debug)) { this.iterableId = nextIterableId.getAndIncrement(); NodeClass snc = superNodeClass; @@ -240,10 +243,9 @@ public final class NodeClass extends FieldIntrospection { this.iterableId = Node.NOT_ITERABLE; this.iterableIds = null; } - nodeIterableCount = Debug.counter("NodeIterable_%s", clazz); assert verifyIterableIds(); - try (Debug.Scope scope = Debug.scope("NodeCosts")) { + try (DebugContext.Scope scope = debug.scope("NodeCosts")) { /* * Note: We do not check for the existence of the node cost annotations during * construction as not every node needs to have them set. However if costs are queried, @@ -268,25 +270,18 @@ public final class NodeClass extends FieldIntrospection { size = s; } assert size != null; - Debug.log("Node cost for node of type __| %s |_, cycles:%s,size:%s", clazz, cycles, size); + debug.log("Node cost for node of type __| %s |_, cycles:%s,size:%s", clazz, cycles, size); } - } private final NodeCycles cycles; private final NodeSize size; public NodeCycles cycles() { - if (Options.VerifyNodeCostOnAccess.getValue() && cycles == NodeCycles.CYCLES_UNSET) { - throw new GraalError("Missing NodeCycles specification in the @NodeInfo annotation of the node %s", this); - } return cycles; } public NodeSize size() { - if (Options.VerifyNodeCostOnAccess.getValue() && size == NodeSize.SIZE_UNSET) { - throw new GraalError("Missing NodeSize specification in the @NodeInfo annotation of the node %s", this); - } return size; } @@ -360,8 +355,7 @@ public final class NodeClass extends FieldIntrospection { return new Fields[]{data, inputs, successors}; } - public int[] iterableIds() { - nodeIterableCount.increment(); + int[] iterableIds() { return iterableIds; } @@ -454,9 +448,11 @@ public final class NodeClass extends FieldIntrospection { public final ArrayList successors = new ArrayList<>(); int directInputs; int directSuccessors; + final DebugContext debug; - protected NodeFieldsScanner(FieldsScanner.CalcOffset calc, NodeClass superNodeClass) { + protected NodeFieldsScanner(FieldsScanner.CalcOffset calc, NodeClass superNodeClass, DebugContext debug) { super(calc); + this.debug = debug; if (superNodeClass != null) { translateInto(superNodeClass.inputs, inputs); translateInto(superNodeClass.successors, successors); @@ -469,10 +465,10 @@ public final class NodeClass extends FieldIntrospection { @SuppressWarnings("try") @Override protected void scanField(Field field, long offset) { - Input inputAnnotation = getAnnotationTimed(field, Node.Input.class); - OptionalInput optionalInputAnnotation = getAnnotationTimed(field, Node.OptionalInput.class); - Successor successorAnnotation = getAnnotationTimed(field, Successor.class); - try (DebugCloseable s = Init_FieldScanningInner.start()) { + Input inputAnnotation = getAnnotationTimed(field, Node.Input.class, debug); + OptionalInput optionalInputAnnotation = getAnnotationTimed(field, Node.OptionalInput.class, debug); + Successor successorAnnotation = getAnnotationTimed(field, Successor.class, debug); + try (DebugCloseable s = Init_FieldScanningInner.start(debug)) { Class type = field.getType(); int modifiers = field.getModifiers(); @@ -532,7 +528,11 @@ public final class NodeClass extends FieldIntrospection { } private static int deepHashCode0(Object o) { - if (o instanceof Object[]) { + if (o == null) { + return 0; + } else if (!o.getClass().isArray()) { + return o.hashCode(); + } else if (o instanceof Object[]) { return Arrays.deepHashCode((Object[]) o); } else if (o instanceof byte[]) { return Arrays.hashCode((byte[]) o); @@ -550,10 +550,8 @@ public final class NodeClass extends FieldIntrospection { return Arrays.hashCode((double[]) o); } else if (o instanceof boolean[]) { return Arrays.hashCode((boolean[]) o); - } else if (o != null) { - return o.hashCode(); } else { - return 0; + throw shouldNotReachHere(); } } @@ -605,30 +603,47 @@ public final class NodeClass extends FieldIntrospection { } private static boolean deepEquals0(Object e1, Object e2) { - assert e1 != null; - boolean eq; - if (e1 instanceof Object[] && e2 instanceof Object[]) { - eq = Arrays.deepEquals((Object[]) e1, (Object[]) e2); - } else if (e1 instanceof byte[] && e2 instanceof byte[]) { - eq = Arrays.equals((byte[]) e1, (byte[]) e2); - } else if (e1 instanceof short[] && e2 instanceof short[]) { - eq = Arrays.equals((short[]) e1, (short[]) e2); - } else if (e1 instanceof int[] && e2 instanceof int[]) { - eq = Arrays.equals((int[]) e1, (int[]) e2); - } else if (e1 instanceof long[] && e2 instanceof long[]) { - eq = Arrays.equals((long[]) e1, (long[]) e2); - } else if (e1 instanceof char[] && e2 instanceof char[]) { - eq = Arrays.equals((char[]) e1, (char[]) e2); - } else if (e1 instanceof float[] && e2 instanceof float[]) { - eq = Arrays.equals((float[]) e1, (float[]) e2); - } else if (e1 instanceof double[] && e2 instanceof double[]) { - eq = Arrays.equals((double[]) e1, (double[]) e2); - } else if (e1 instanceof boolean[] && e2 instanceof boolean[]) { - eq = Arrays.equals((boolean[]) e1, (boolean[]) e2); + if (e1 == e2) { + return true; + } else if (e1 == null || e2 == null) { + return false; + } else if (!e1.getClass().isArray() || e1.getClass() != e2.getClass()) { + return e1.equals(e2); + } else if (e1 instanceof Object[] && e2 instanceof Object[]) { + return deepEquals((Object[]) e1, (Object[]) e2); + } else if (e1 instanceof int[]) { + return Arrays.equals((int[]) e1, (int[]) e2); + } else if (e1 instanceof long[]) { + return Arrays.equals((long[]) e1, (long[]) e2); + } else if (e1 instanceof byte[]) { + return Arrays.equals((byte[]) e1, (byte[]) e2); + } else if (e1 instanceof char[]) { + return Arrays.equals((char[]) e1, (char[]) e2); + } else if (e1 instanceof short[]) { + return Arrays.equals((short[]) e1, (short[]) e2); + } else if (e1 instanceof float[]) { + return Arrays.equals((float[]) e1, (float[]) e2); + } else if (e1 instanceof double[]) { + return Arrays.equals((double[]) e1, (double[]) e2); + } else if (e1 instanceof boolean[]) { + return Arrays.equals((boolean[]) e1, (boolean[]) e2); } else { - eq = e1.equals(e2); + throw shouldNotReachHere(); } - return eq; + } + + private static boolean deepEquals(Object[] a1, Object[] a2) { + int length = a1.length; + if (a2.length != length) { + return false; + } + + for (int i = 0; i < length; i++) { + if (!deepEquals0(a1[i], a2[i])) { + return false; + } + } + return true; } public boolean dataEquals(Node a, Node b) { @@ -799,10 +814,12 @@ public final class NodeClass extends FieldIntrospection { /** * The template used to build the {@link Verbosity#Name} version. Variable parts are specified - * using {i#inputName} or {p#propertyName}. + * using {i#inputName} or {p#propertyName}. If no + * {@link NodeInfo#nameTemplate() template} is specified, it uses {@link NodeInfo#shortName()}. + * If none of the two is specified, it returns an empty string. */ public String getNameTemplate() { - return nameTemplate.isEmpty() ? shortName() : nameTemplate; + return nameTemplate; } interface InplaceUpdateClosure { @@ -810,15 +827,15 @@ public final class NodeClass extends FieldIntrospection { Node replacement(Node node, Edges.Type type); } - static Map addGraphDuplicate(final Graph graph, final Graph oldGraph, int estimatedNodeCount, Iterable nodes, final DuplicationReplacement replacements) { - final Map newNodes; + static EconomicMap addGraphDuplicate(final Graph graph, final Graph oldGraph, int estimatedNodeCount, Iterable nodes, final DuplicationReplacement replacements) { + final EconomicMap newNodes; int denseThreshold = oldGraph.getNodeCount() + oldGraph.getNodesDeletedSinceLastCompression() >> 4; if (estimatedNodeCount > denseThreshold) { // Use dense map - newNodes = new NodeNodeMap(oldGraph); + newNodes = new NodeMap<>(oldGraph); } else { // Use sparse map - newNodes = newIdentityMap(); + newNodes = EconomicMap.create(Equivalence.IDENTITY); } createNodeDuplicates(graph, nodes, replacements, newNodes); @@ -859,7 +876,7 @@ public final class NodeClass extends FieldIntrospection { return newNodes; } - private static void createNodeDuplicates(final Graph graph, Iterable nodes, final DuplicationReplacement replacements, final Map newNodes) { + private static void createNodeDuplicates(final Graph graph, Iterable nodes, final DuplicationReplacement replacements, final EconomicMap newNodes) { for (Node node : nodes) { if (node != null) { assert !node.isDeleted() : "trying to duplicate deleted node: " + node; @@ -868,15 +885,9 @@ public final class NodeClass extends FieldIntrospection { replacement = replacements.replacement(node); } if (replacement != node) { - if (Fingerprint.ENABLED) { - Fingerprint.submit("replacing %s with %s", node, replacement); - } assert replacement != null; newNodes.put(node, replacement); } else { - if (Fingerprint.ENABLED) { - Fingerprint.submit("duplicating %s", node); - } Node newNode = node.clone(graph, WithAllEdges); assert newNode.getNodeClass().isLeafNode() || newNode.hasNoUsages(); assert newNode.getClass() == node.getClass(); @@ -886,12 +897,12 @@ public final class NodeClass extends FieldIntrospection { } } - private static void transferEdgesDifferentNodeClass(final Graph graph, final DuplicationReplacement replacements, final Map newNodes, Node oldNode, Node node) { + private static void transferEdgesDifferentNodeClass(final Graph graph, final DuplicationReplacement replacements, final EconomicMap newNodes, Node oldNode, Node node) { transferEdges(graph, replacements, newNodes, oldNode, node, Edges.Type.Inputs); transferEdges(graph, replacements, newNodes, oldNode, node, Edges.Type.Successors); } - private static void transferEdges(final Graph graph, final DuplicationReplacement replacements, final Map newNodes, Node oldNode, Node node, Edges.Type type) { + private static void transferEdges(final Graph graph, final DuplicationReplacement replacements, final EconomicMap newNodes, Node oldNode, Node node, Edges.Type type) { NodeClass nodeClass = node.getNodeClass(); NodeClass oldNodeClass = oldNode.getNodeClass(); Edges oldEdges = oldNodeClass.getEdges(type); @@ -926,6 +937,14 @@ public final class NodeClass extends FieldIntrospection { return isLeafNode; } + public int getLeafId() { + return this.leafId; + } + + public NodeClass getSuperNodeClass() { + return superNodeClass; + } + public long inputsIteration() { return inputsIteration; } @@ -1086,6 +1105,25 @@ public final class NodeClass extends FieldIntrospection { return new RawEdgesIterator(node, mask); } } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Iterator iterator = iterator(); + boolean first = true; + sb.append("succs="); + sb.append('['); + while (iterator.hasNext()) { + Node input = iterator.next(); + if (!first) { + sb.append(", "); + } + sb.append(input); + first = false; + } + sb.append(']'); + return sb.toString(); + } }; } @@ -1101,6 +1139,25 @@ public final class NodeClass extends FieldIntrospection { return new RawEdgesIterator(node, mask); } } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Iterator iterator = iterator(); + boolean first = true; + sb.append("inputs="); + sb.append('['); + while (iterator.hasNext()) { + Node input = iterator.next(); + if (!first) { + sb.append(", "); + } + sb.append(input); + first = false; + } + sb.append(']'); + return sb.toString(); + } }; } @@ -1117,13 +1174,15 @@ public final class NodeClass extends FieldIntrospection { assert other.getNodeClass() == this; while (myMask != 0) { long offset = (myMask & OFFSET_MASK); - Object v1 = UNSAFE.getObject(node, offset); - Object v2 = UNSAFE.getObject(other, offset); if ((myMask & LIST_MASK) == 0) { + Object v1 = Edges.getNodeUnsafe(node, offset); + Object v2 = Edges.getNodeUnsafe(other, offset); if (v1 != v2) { return false; } } else { + Object v1 = Edges.getNodeListUnsafe(node, offset); + Object v2 = Edges.getNodeListUnsafe(other, offset); if (!Objects.equals(v1, v2)) { return false; } @@ -1178,7 +1237,7 @@ public final class NodeClass extends FieldIntrospection { if (curNode != null) { Node newNode = consumer.apply(node, curNode); if (newNode != curNode) { - UNSAFE.putObject(node, offset, newNode); + Edges.putNodeUnsafe(node, offset, newNode); } } } else { @@ -1211,7 +1270,7 @@ public final class NodeClass extends FieldIntrospection { Node curNode = Edges.getNodeUnsafe(node, offset); if (curNode != null) { node.updatePredecessor(curNode, null); - UNSAFE.putObject(node, offset, null); + Edges.putNodeUnsafe(node, offset, null); } } else { unregisterAtSuccessorsAsPredecessorHelper(node, offset); @@ -1276,9 +1335,9 @@ public final class NodeClass extends FieldIntrospection { while (myMask != 0) { long offset = (myMask & OFFSET_MASK); if ((myMask & LIST_MASK) == 0) { - Object curNode = UNSAFE.getObject(node, offset); + Object curNode = Edges.getNodeUnsafe(node, offset); if (curNode == key) { - UNSAFE.putObject(node, offset, replacement); + Edges.putNodeUnsafe(node, offset, replacement); return true; } } else { @@ -1333,7 +1392,7 @@ public final class NodeClass extends FieldIntrospection { if (curNode.hasNoUsages()) { node.maybeNotifyZeroUsages(curNode); } - UNSAFE.putObject(node, offset, null); + Edges.putNodeUnsafe(node, offset, null); } } else { unregisterAtInputsAsUsageHelper(node, offset); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeCollectionsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeCollectionsProvider.java deleted file mode 100644 index 848c9efb041..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeCollectionsProvider.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.graph; - -import java.util.Map; -import java.util.Set; - -import org.graalvm.compiler.api.collections.CollectionsProvider; - -/** - * Extends {@link CollectionsProvider} with support for creating {@link Node} based collections. - */ -public interface NodeCollectionsProvider extends CollectionsProvider { - - /** - * Creates a set of {@link Node}s that uses reference-equality in place of object-equality when - * comparing entries. - */ - Set newNodeIdentitySet(); - - /** - * Creates a map whose keys are {@link Node}s that uses reference-equality in place of - * object-equality when comparing keys. All {@link Node} keys must be in the same graph. - */ - Map newNodeIdentityMap(); - - /** - * Creates a map whose keys are {@link Node}s that uses reference-equality in place of - * object-equality when comparing keys. All {@link Node} keys must be in the same graph. - */ - Map newNodeIdentityMap(int expectedMaxSize); - - /** - * Creates a map whose keys are {@link Node}s that uses reference-equality in place of - * object-equality when comparing keys. All {@link Node} keys must be in the same graph. - * - * @param initFrom the returned map is populated with the entries in this map - */ - Map newNodeIdentityMap(Map initFrom); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java index 32ab50d5b65..5b0edb8b39c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -22,12 +22,14 @@ */ package org.graalvm.compiler.graph; -import java.util.AbstractMap.SimpleEntry; import java.util.Arrays; import java.util.Iterator; -import java.util.Map.Entry; +import java.util.function.BiFunction; -public class NodeMap extends NodeIdAccessor { +import org.graalvm.util.EconomicMap; +import org.graalvm.util.MapCursor; + +public class NodeMap extends NodeIdAccessor implements EconomicMap { private static final int MIN_REALLOC_SIZE = 16; @@ -43,6 +45,7 @@ public class NodeMap extends NodeIdAccessor { this.values = Arrays.copyOf(copyFrom.values, copyFrom.values.length); } + @Override @SuppressWarnings("unchecked") public T get(Node node) { assert check(node); @@ -62,16 +65,15 @@ public class NodeMap extends NodeIdAccessor { assert check(node); } + @Override public boolean isEmpty() { - return !entries().iterator().hasNext(); + throw new UnsupportedOperationException("isEmpty() is not supported for performance reasons"); } - public boolean containsKey(Object key) { - if (key instanceof Node) { - Node node = (Node) key; - if (node.graph() == graph()) { - return get(node) != null; - } + @Override + public boolean containsKey(Node node) { + if (node.graph() == graph()) { + return get(node) != null; } return false; } @@ -96,7 +98,7 @@ public class NodeMap extends NodeIdAccessor { public void setAndGrow(Node node, T value) { checkAndGrow(node); - values[getNodeId(node)] = value; + set(node, value); } /** @@ -107,12 +109,17 @@ public class NodeMap extends NodeIdAccessor { return graph.getNode(i); } + @Override public int size() { + throw new UnsupportedOperationException("size() is not supported for performance reasons"); + } + + public int capacity() { return values.length; } public boolean isNew(Node node) { - return getNodeId(node) >= size(); + return getNodeId(node) >= capacity(); } private boolean check(Node node) { @@ -121,16 +128,92 @@ public class NodeMap extends NodeIdAccessor { return true; } + @Override public void clear() { Arrays.fill(values, null); } - public Iterable> entries() { - return new Iterable>() { + @Override + public Iterable getKeys() { + return new Iterable() { @Override - public Iterator> iterator() { - return new Iterator>() { + public Iterator iterator() { + return new Iterator() { + + int i = 0; + + @Override + public boolean hasNext() { + forward(); + return i < NodeMap.this.values.length; + } + + @Override + public Node next() { + final int pos = i; + final Node key = NodeMap.this.getKey(pos); + i++; + forward(); + return key; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + private void forward() { + while (i < NodeMap.this.values.length && (NodeMap.this.getKey(i) == null || NodeMap.this.values[i] == null)) { + i++; + } + } + }; + } + }; + } + + @Override + public MapCursor getEntries() { + return new MapCursor() { + + int current = -1; + + @Override + public boolean advance() { + current++; + while (current < NodeMap.this.values.length && (NodeMap.this.values[current] == null || NodeMap.this.getKey(current) == null)) { + current++; + } + return current < NodeMap.this.values.length; + } + + @Override + public Node getKey() { + return NodeMap.this.getKey(current); + } + + @SuppressWarnings("unchecked") + @Override + public T getValue() { + return (T) NodeMap.this.values[current]; + } + + @Override + public void remove() { + assert NodeMap.this.values[current] != null; + NodeMap.this.values[current] = null; + } + }; + } + + @Override + public Iterable getValues() { + return new Iterable() { + + @Override + public Iterator iterator() { + return new Iterator() { int i = 0; @@ -142,23 +225,12 @@ public class NodeMap extends NodeIdAccessor { @SuppressWarnings("unchecked") @Override - public Entry next() { + public T next() { final int pos = i; - Node key = NodeMap.this.getKey(pos); - T value = (T) NodeMap.this.values[pos]; + final T value = (T) NodeMap.this.values[pos]; i++; forward(); - return new SimpleEntry(key, value) { - - private static final long serialVersionUID = 7813842391085737738L; - - @Override - public T setValue(T v) { - T oldv = super.setValue(v); - NodeMap.this.values[pos] = v; - return oldv; - } - }; + return value; } @Override @@ -178,24 +250,42 @@ public class NodeMap extends NodeIdAccessor { @Override public String toString() { - Iterator> i = entries().iterator(); - if (!i.hasNext()) { + MapCursor i = getEntries(); + if (!i.advance()) { return "{}"; } StringBuilder sb = new StringBuilder(); sb.append('{'); while (true) { - Entry e = i.next(); - Node key = e.getKey(); - T value = e.getValue(); + Node key = i.getKey(); + T value = i.getValue(); sb.append(key); sb.append('='); sb.append(value); - if (!i.hasNext()) { + if (!i.advance()) { return sb.append('}').toString(); } sb.append(',').append(' '); } } + + @Override + public T put(Node key, T value) { + T result = get(key); + set(key, value); + return result; + } + + @Override + public T removeKey(Node key) { + return put(key, null); + } + + @Override + public void replaceAll(BiFunction function) { + for (Node n : getKeys()) { + put(n, function.apply(n, get(n))); + } + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeNodeMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeNodeMap.java deleted file mode 100644 index 31e4071d688..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeNodeMap.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.graph; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -public final class NodeNodeMap extends NodeMap implements Map { - - public NodeNodeMap(Graph graph) { - super(graph); - } - - public NodeNodeMap(NodeNodeMap copyFrom) { - super(copyFrom); - } - - @Override - public Node get(Object key) { - return super.get((Node) key); - } - - @Override - public Node put(Node key, Node value) { - Node oldValue = super.get(key); - super.set(key, value); - return oldValue; - } - - @Override - public Node remove(Object key) { - throw new UnsupportedOperationException("Cannot remove keys from this map"); - } - - @Override - public void putAll(Map m) { - for (Entry entry : m.entrySet()) { - put(entry.getKey(), entry.getValue()); - } - } - - @Override - public Set keySet() { - HashSet entries = new HashSet<>(); - for (int i = 0; i < values.length; ++i) { - Object v = values[i]; - if (v != null) { - Node key = getKey(i); - if (key != null) { - entries.add(key); - } - } - } - /* - * The normal contract for entrySet is that modifications of the set are reflected in the - * underlying data structure. For simplicity don't allow that but complain if someone tries - * to use it that way. - */ - return Collections.unmodifiableSet(entries); - } - - @Override - public Collection values() { - ArrayList result = new ArrayList<>(this.size()); - for (int i = 0; i < values.length; ++i) { - Object v = values[i]; - if (v != null) { - result.add((Node) v); - } - } - return result; - } - - @Override - public Set> entrySet() { - HashSet> entries = new HashSet<>(); - for (Map.Entry entry : entries()) { - entries.add(entry); - } - /* - * The normal contract for entrySet is that modifications of the set are reflected in the - * underlying data structure. For simplicity don't allow that but complain if someone tries - * to use it that way. - */ - return Collections.unmodifiableSet(entries); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java index f747d79a40e..688eb793968 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java @@ -36,9 +36,15 @@ public class NodeSourcePosition extends BytecodePosition { * The receiver of the method this frame refers to. */ private final JavaConstant receiver; + private final int hashCode; public NodeSourcePosition(JavaConstant receiver, NodeSourcePosition caller, ResolvedJavaMethod method, int bci) { super(caller, method, bci); + if (caller == null) { + this.hashCode = 31 * bci + method.hashCode(); + } else { + this.hashCode = caller.hashCode * 7 + 31 * bci + method.hashCode(); + } this.receiver = receiver; assert receiver == null || method.getDeclaringClass().isInstance(receiver); } @@ -50,6 +56,9 @@ public class NodeSourcePosition extends BytecodePosition { } if (obj != null && getClass() == obj.getClass()) { NodeSourcePosition that = (NodeSourcePosition) obj; + if (hashCode != that.hashCode) { + return false; + } if (this.getBCI() == that.getBCI() && Objects.equals(this.getMethod(), that.getMethod()) && Objects.equals(this.getCaller(), that.getCaller()) && Objects.equals(this.receiver, that.receiver)) { return true; @@ -58,6 +67,11 @@ public class NodeSourcePosition extends BytecodePosition { return false; } + @Override + public int hashCode() { + return hashCode; + } + public JavaConstant getReceiver() { return receiver; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java index 5e82577feaa..754e50e90b6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeStack.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -23,14 +23,21 @@ package org.graalvm.compiler.graph; public final class NodeStack { - - private static final int INITIAL_SIZE = 8; + private static final int DEFAULT_INITIAL_SIZE = 8; protected Node[] values; public int tos; public NodeStack() { - values = new Node[INITIAL_SIZE]; + this(DEFAULT_INITIAL_SIZE); + } + + public NodeStack(int initialSize) { + values = new Node[initialSize]; + } + + public int size() { + return tos; } public void push(Node n) { @@ -49,6 +56,10 @@ public final class NodeStack { values = newValues; } + public Node get(int index) { + return values[index]; + } + public Node pop() { assert tos > 0 : "stack must be non-empty"; return values[--tos]; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java index b84fadadbf4..37f7a76629b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeUsageIterable.java @@ -24,6 +24,8 @@ package org.graalvm.compiler.graph; import static org.graalvm.compiler.graph.Graph.isModificationCountsEnabled; +import java.util.Iterator; + import org.graalvm.compiler.graph.iterators.NodeIterable; class NodeUsageIterable implements NodeIterable { @@ -62,4 +64,23 @@ class NodeUsageIterable implements NodeIterable { public int count() { return node.getUsageCount(); } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Iterator iterator = iterator(); + boolean first = true; + sb.append("usages="); + sb.append('['); + while (iterator.hasNext()) { + Node input = iterator.next(); + if (!first) { + sb.append(", "); + } + sb.append(input); + first = false; + } + sb.append(']'); + return sb.toString(); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java index 335826d2cdf..e7429261ad5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeWorkList.java @@ -27,6 +27,8 @@ import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Queue; +import org.graalvm.compiler.debug.DebugContext; + public abstract class NodeWorkList implements Iterable { protected final Queue worklist; @@ -70,20 +72,21 @@ public abstract class NodeWorkList implements Iterable { } public static final class IterativeNodeWorkList extends NodeWorkList { - private static final int EXPLICIT_BITMAP_THRESHOLD = 10; protected NodeBitMap inQueue; - private int iterationLimit = Integer.MAX_VALUE; + private final DebugContext debug; + private int iterationLimit; private Node firstNoChange; private Node lastPull; private Node lastChain; public IterativeNodeWorkList(Graph graph, boolean fill, int iterationLimitPerNode) { super(graph, fill); - if (iterationLimitPerNode > 0) { - iterationLimit = iterationLimitPerNode * graph.getNodeCount(); - } + debug = graph.getDebug(); + assert iterationLimitPerNode > 0; + long limit = (long) iterationLimitPerNode * graph.getNodeCount(); + iterationLimit = (int) Long.min(Integer.MAX_VALUE, limit); } @Override @@ -92,7 +95,11 @@ public abstract class NodeWorkList implements Iterable { @Override public boolean hasNext() { dropDeleted(); - return iterationLimit > 0 && !worklist.isEmpty(); + if (iterationLimit <= 0) { + debug.log(DebugContext.INFO_LEVEL, "Exceeded iteration limit in IterativeNodeWorkList"); + return false; + } + return !worklist.isEmpty(); } @Override @@ -137,7 +144,7 @@ public abstract class NodeWorkList implements Iterable { } } } - assert checkInfiniteWork(node) : "Readded " + node; + assert checkInfiniteWork(node) : "Re-added " + node; if (inQueue != null) { inQueue.markAndGrow(node); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/TypedGraphNodeIterator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/TypedGraphNodeIterator.java index e018065bbbe..a879bbe978b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/TypedGraphNodeIterator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/TypedGraphNodeIterator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2017, 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 @@ -22,7 +22,6 @@ */ package org.graalvm.compiler.graph; -import java.util.Arrays; import java.util.Iterator; import java.util.NoSuchElementException; @@ -40,7 +39,6 @@ class TypedGraphNodeIterator implements Iterator ids = clazz.iterableIds(); currentIdIndex = 0; current = new Node[ids.length]; - Arrays.fill(current, Graph.PLACE_HOLDER); needsForward = true; } @@ -67,7 +65,7 @@ class TypedGraphNodeIterator implements Iterator int startIdx = currentIdIndex; while (true) { Node next; - if (current() == Graph.PLACE_HOLDER) { + if (current() == null) { next = graph.getIterableNodeStart(ids[currentIdIndex]); } else { next = graph.getIterableNodeNext(current().typeCacheNext); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicate.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicate.java index 84ace707a11..267497669d6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicate.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicate.java @@ -22,13 +22,20 @@ */ package org.graalvm.compiler.graph.iterators; +import java.util.function.Predicate; + import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodePredicates.AndPredicate; -public interface NodePredicate { +public interface NodePredicate extends Predicate { boolean apply(Node n); + @Override + default boolean test(Node n) { + return apply(n); + } + default NodePredicate and(NodePredicate np) { return new AndPredicate(this, np); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java index f52306dd68f..a467a742e12 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/iterators/NodePredicates.java @@ -105,6 +105,7 @@ public abstract class NodePredicates { return !a.apply(n); } + @Override public NodePredicate negate() { return a; } @@ -148,6 +149,7 @@ public abstract class NodePredicates { return this; } + @Override public NodePredicate negate() { return new NegativeTypePredicate(this); } @@ -183,6 +185,7 @@ public abstract class NodePredicates { return this; } + @Override public NodePredicate negate() { return new PositiveTypePredicate(this); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/spi/CanonicalizerTool.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/spi/CanonicalizerTool.java index e7fc59fe646..c952b746bc2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/spi/CanonicalizerTool.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/spi/CanonicalizerTool.java @@ -28,6 +28,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.options.OptionValues; public interface CanonicalizerTool { @@ -49,8 +50,10 @@ public interface CanonicalizerTool { boolean allUsagesAvailable(); /** - * Indicates whether the target platform supports comparison of integers of a particular bit - * width. This check is used by canonicalizations that might introduce subword compares. + * Indicates the smallest width for comparing an integer value on the target platform. If this + * method returns null, then there is no known smallest compare width. */ - boolean supportSubwordCompare(int bits); + Integer smallestCompareWidth(); + + OptionValues getOptions(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java index 8d3b056e404..53dc46d92dc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java @@ -31,8 +31,6 @@ import static jdk.vm.ci.aarch64.AArch64.zr; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp; -import java.util.Set; - import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64Address; @@ -66,6 +64,7 @@ import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.Register; @@ -140,35 +139,39 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { } crb.blockComment("[method prologue]"); - if (ZapStackOnMethodEntry.getValue()) { - try (ScratchRegister sc = masm.getScratchRegister()) { - Register scratch = sc.getRegister(); - int intSize = 4; - AArch64Address address = AArch64Address.createPreIndexedImmediateAddress(scratch, -intSize); - try (ScratchRegister sc2 = masm.getScratchRegister()) { - Register value = sc2.getRegister(); - masm.mov(value, 0xC1C1C1C1); - for (int i = 0; i < frameSize; i += intSize) { - masm.str(32, value, address); - } - } - masm.mov(64, sp, scratch); - } - } else { - if (AArch64MacroAssembler.isArithmeticImmediate(totalFrameSize)) { + try (ScratchRegister sc = masm.getScratchRegister()) { + int wordSize = crb.target.arch.getWordSize(); + Register rscratch1 = sc.getRegister(); + assert totalFrameSize > 0; + if (frameSize < 1 << 9) { masm.sub(64, sp, sp, totalFrameSize); + masm.stp(64, fp, lr, AArch64Address.createScaledImmediateAddress(sp, frameSize / wordSize)); } else { - try (ScratchRegister sc2 = masm.getScratchRegister()) { - Register scratch2 = sc2.getRegister(); - masm.mov(scratch2, totalFrameSize); - masm.sub(64, sp, sp, scratch2); + masm.stp(64, fp, lr, AArch64Address.createPreIndexedImmediateAddress(sp, -2)); + if (frameSize < 1 << 12) { + masm.sub(64, sp, sp, totalFrameSize - 2 * wordSize); + } else { + masm.mov(rscratch1, totalFrameSize - 2 * wordSize); + masm.sub(64, sp, sp, rscratch1); } } } + if (ZapStackOnMethodEntry.getValue(crb.getOptions())) { + try (ScratchRegister sc = masm.getScratchRegister()) { + Register scratch = sc.getRegister(); + int longSize = 8; + masm.mov(64, scratch, sp); + AArch64Address address = AArch64Address.createPostIndexedImmediateAddress(scratch, longSize); + try (ScratchRegister sc2 = masm.getScratchRegister()) { + Register value = sc2.getRegister(); + masm.mov(value, 0xBADDECAFFC0FFEEL); + for (int i = 0; i < frameSize; i += longSize) { + masm.str(64, value, address); + } + } - AArch64Address address2 = AArch64Address.createPairUnscaledImmediateAddress(sp, frameSize / 8); // XXX - masm.stp(64, fp, lr, address2); - + } + } crb.blockComment("[code body]"); } @@ -176,23 +179,28 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { public void leave(CompilationResultBuilder crb) { AArch64MacroAssembler masm = (AArch64MacroAssembler) crb.asm; FrameMap frameMap = crb.frameMap; - final int frameSize = frameMap.frameSize(); final int totalFrameSize = frameMap.totalFrameSize(); crb.blockComment("[method epilogue]"); - - AArch64Address address2 = AArch64Address.createPairUnscaledImmediateAddress(sp, frameSize / 8); // XXX - masm.ldp(64, fp, lr, address2); - - if (AArch64MacroAssembler.isArithmeticImmediate(totalFrameSize)) { - masm.add(64, sp, sp, totalFrameSize); - } else { - try (ScratchRegister sc = masm.getScratchRegister()) { - Register scratch = sc.getRegister(); - masm.mov(scratch, totalFrameSize); - masm.add(64, sp, sp, scratch); + try (ScratchRegister sc = masm.getScratchRegister()) { + int wordSize = crb.target.arch.getWordSize(); + Register rscratch1 = sc.getRegister(); + final int frameSize = frameMap.frameSize(); + assert totalFrameSize > 0; + if (frameSize < 1 << 9) { + masm.ldp(64, fp, lr, AArch64Address.createScaledImmediateAddress(sp, frameSize / wordSize)); + masm.add(64, sp, sp, totalFrameSize); + } else { + if (frameSize < 1 << 12) { + masm.add(64, sp, sp, totalFrameSize - 2 * wordSize); + } else { + masm.mov(rscratch1, totalFrameSize - 2 * wordSize); + masm.add(64, sp, sp, rscratch1); + } + masm.ldp(64, fp, lr, AArch64Address.createPostIndexedImmediateAddress(sp, 2)); } } + } @Override @@ -218,7 +226,7 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); - CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, compilationResult); + CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, lir.getOptions(), lir.getDebug(), compilationResult); crb.setTotalFrameSize(frameMap.totalFrameSize()); crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); @@ -227,7 +235,7 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { } if (stub != null) { - Set destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); + EconomicSet destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); updateStub(stub, destroyedCallerRegisters, gen.getCalleeSaveInfo(), frameMap); } return crb; @@ -315,13 +323,13 @@ public class AArch64HotSpotBackend extends HotSpotHostBackend { } @Override - public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig) { + public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; - return new AArch64HotSpotRegisterAllocationConfig(registerConfigNonNull); + return new AArch64HotSpotRegisterAllocationConfig(registerConfigNonNull, allocationRestrictedTo); } @Override - public Set translateToCallerRegisters(Set calleeRegisters) { + public EconomicSet translateToCallerRegisters(EconomicSet calleeRegisters) { return calleeRegisters; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java index 64d47cb243d..1b8d7061a80 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java @@ -27,8 +27,9 @@ import static jdk.vm.ci.common.InitTimer.timer; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeProvider; -import org.graalvm.compiler.core.aarch64.AArch64AddressLowering; -import org.graalvm.compiler.core.aarch64.AArch64SuitesProvider; +import org.graalvm.compiler.core.aarch64.AArch64AddressLoweringByUse; +import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool; +import org.graalvm.compiler.core.aarch64.AArch64SuitesCreator; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotBackendFactory; @@ -46,10 +47,9 @@ import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSnippetReflectionProvider; import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider; -import org.graalvm.compiler.hotspot.nodes.HotSpotNodeCostProvider; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.nodes.spi.NodeCostProvider; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.aarch64.AArch64GraphBuilderPlugins; @@ -106,7 +106,6 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { HotSpotSuitesProvider suites; HotSpotWordTypes wordTypes; Plugins plugins; - NodeCostProvider nodeCostProvider; BytecodeProvider bytecodeProvider; try (InitTimer t = timer("create providers")) { try (InitTimer rt = timer("create HotSpotRegisters provider")) { @@ -124,11 +123,8 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { try (InitTimer rt = timer("create Lowerer provider")) { lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, target); } - try (InitTimer rt = timer("create NodeCost provider")) { - nodeCostProvider = createNodeCostProvider(); - } HotSpotStampProvider stampProvider = new HotSpotStampProvider(); - Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, nodeCostProvider); + Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider); try (InitTimer rt = timer("create SnippetReflection provider")) { snippetReflection = createSnippetReflection(graalRuntime, constantReflection, wordTypes); @@ -137,16 +133,16 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection); } try (InitTimer rt = timer("create Replacements provider")) { - replacements = createReplacements(p, snippetReflection, bytecodeProvider); + replacements = createReplacements(graalRuntime.getOptions(), p, snippetReflection, bytecodeProvider); } try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { - plugins = createGraphBuilderPlugins(config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, stampProvider); + plugins = createGraphBuilderPlugins(compilerConfiguration, config, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, stampProvider); replacements.setGraphBuilderPlugins(plugins); } try (InitTimer rt = timer("create Suites provider")) { suites = createSuites(config, graalRuntime, compilerConfiguration, plugins); } - providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, nodeCostProvider, suites, registers, + providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, snippetReflection, wordTypes, plugins); } @@ -155,11 +151,11 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { } } - protected Plugins createGraphBuilderPlugins(GraalHotSpotVMConfig config, HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, - HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, - HotSpotStampProvider stampProvider) { - Plugins plugins = HotSpotGraphBuilderPlugins.create(config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); - AArch64GraphBuilderPlugins.register(plugins, foreignCalls, replacements.getReplacementBytecodeProvider()); + protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotConstantReflectionProvider constantReflection, + HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, + HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) { + Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); + AArch64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider()); return plugins; } @@ -171,8 +167,8 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { return new HotSpotRegisters(AArch64HotSpotRegisterConfig.threadRegister, AArch64HotSpotRegisterConfig.heapBaseRegister, sp); } - protected HotSpotReplacementsImpl createReplacements(Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { - return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); + protected HotSpotReplacementsImpl createReplacements(OptionValues options, Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { + return new HotSpotReplacementsImpl(options, p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); } protected HotSpotHostForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, @@ -181,7 +177,7 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { } protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins) { - return new HotSpotSuitesProvider(new AArch64SuitesProvider(compilerConfiguration, plugins), config, runtime, new AArch64AddressLowering()); + return new AArch64HotSpotSuitesProvider(new AArch64SuitesCreator(compilerConfiguration, plugins), config, runtime, new AArch64AddressLoweringByUse(new AArch64LIRKindTool())); } protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) { @@ -193,10 +189,6 @@ public class AArch64HotSpotBackendFactory implements HotSpotBackendFactory { return new AArch64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, constantReflection, target); } - protected HotSpotNodeCostProvider createNodeCostProvider() { - return new AArchHotSpotNodeCostProvider(); - } - protected static Value[] createNativeABICallerSaveRegisters(@SuppressWarnings("unused") GraalHotSpotVMConfig config, RegisterConfig regConfig) { AArch64HotSpotRegisterConfig conf = (AArch64HotSpotRegisterConfig) regConfig; RegisterArray callerSavedRegisters = conf.getCallerSaveRegisters(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java index d7aefd8293d..054fb34bda9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java @@ -22,25 +22,24 @@ */ package org.graalvm.compiler.hotspot.aarch64; -import static org.graalvm.compiler.core.common.LocationIdentity.any; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; -import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import static jdk.vm.ci.aarch64.AArch64.r0; import static jdk.vm.ci.aarch64.AArch64.r3; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static jdk.vm.ci.meta.Value.ILLEGAL; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; +import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; +import static org.graalvm.word.LocationIdentity.any; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.WordTypes; import jdk.vm.ci.code.CallingConvention; @@ -63,7 +62,7 @@ public class AArch64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsP } @Override - public void initialize(HotSpotProviders providers) { + public void initialize(HotSpotProviders providers, OptionValues options) { GraalHotSpotVMConfig config = runtime.getVMConfig(); TargetDescription target = providers.getCodeCache().getTarget(); PlatformKind word = target.arch.getWordKind(); @@ -76,16 +75,12 @@ public class AArch64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsP register(new HotSpotForeignCallLinkageImpl(HotSpotBackend.EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF, exceptionCc, null, NOT_REEXECUTABLE, any())); register(new HotSpotForeignCallLinkageImpl(HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF, exceptionCc, null, NOT_REEXECUTABLE, any())); - if (PreferGraalStubs.getValue()) { - throw GraalError.unimplemented("PreferGraalStubs"); - } - // These stubs do callee saving if (config.useCRC32Intrinsics) { registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF, NOT_REEXECUTABLE, any()); } - super.initialize(providers); + super.initialize(providers, options); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java index 52fbb28d51a..f2eb47b145a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java @@ -68,16 +68,19 @@ public class AArch64HotSpotJumpToExceptionHandlerInCallerOp extends AArch64HotSp public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { leaveFrame(crb, masm, /* emitSafepoint */false); - // Restore sp from fp if the exception PC is a method handle call site. - try (ScratchRegister sc = masm.getScratchRegister()) { - Register scratch = sc.getRegister(); - AArch64Address address = masm.makeAddress(thread, isMethodHandleReturnOffset, scratch, 4, /* allowOverwrite */false); - masm.ldr(32, scratch, address); - Label noRestore = new Label(); - masm.cbz(32, scratch, noRestore); - masm.mov(64, sp, fp); - masm.bind(noRestore); + if (System.getProperty("java.specification.version").compareTo("1.8") < 0) { + // Restore sp from fp if the exception PC is a method handle call site. + try (ScratchRegister sc = masm.getScratchRegister()) { + Register scratch = sc.getRegister(); + AArch64Address address = masm.makeAddress(thread, isMethodHandleReturnOffset, scratch, 4, /* allowOverwrite */false); + masm.ldr(32, scratch, address); + Label noRestore = new Label(); + masm.cbz(32, scratch, noRestore); + masm.mov(64, sp, fp); + masm.bind(noRestore); + } } + masm.jmp(asRegister(handlerInCallerPc)); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java index d8b03b30c85..1803ea3adbb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java @@ -29,24 +29,25 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; import java.util.function.Function; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler.PrefetchMode; import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; import org.graalvm.compiler.core.aarch64.AArch64ArithmeticLIRGenerator; import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator; +import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -58,9 +59,11 @@ import org.graalvm.compiler.lir.SwitchStrategy; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.aarch64.AArch64AddressValue; +import org.graalvm.compiler.lir.aarch64.AArch64CCall; import org.graalvm.compiler.lir.aarch64.AArch64Call; import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp; import org.graalvm.compiler.lir.aarch64.AArch64FrameMapBuilder; +import org.graalvm.compiler.lir.aarch64.AArch64Move; import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp; import org.graalvm.compiler.lir.aarch64.AArch64PrefetchOp; import org.graalvm.compiler.lir.gen.LIRGenerationResult; @@ -91,7 +94,7 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H private HotSpotDebugInfoBuilder debugInfoBuilder; protected AArch64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes) { - this(new AArch64HotSpotLIRKindTool(), new AArch64ArithmeticLIRGenerator(), new AArch64HotSpotMoveFactory(), providers, config, lirGenRes); + this(new AArch64LIRKindTool(), new AArch64ArithmeticLIRGenerator(), new AArch64HotSpotMoveFactory(), providers, config, lirGenRes); } protected AArch64HotSpotLIRGenerator(LIRKindTool lirKindTool, AArch64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config, @@ -129,6 +132,19 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H } @Override + public void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args) { + Value[] argLocations = new Value[args.length]; + getResult().getFrameMapBuilder().callsMethod(nativeCallingConvention); + for (int i = 0; i < args.length; i++) { + Value arg = args[i]; + AllocatableValue loc = nativeCallingConvention.getArgument(i); + emitMove(loc, arg); + argLocations[i] = loc; + } + Value ptr = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(address)); + append(new AArch64CCall(nativeCallingConvention.getReturn(), ptr, argLocations)); + } + public SaveRegistersOp emitSaveAllRegisters() { throw GraalError.unimplemented(); } @@ -193,8 +209,8 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H // metaspace pointer Variable result = newVariable(LIRKind.value(AArch64Kind.DWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0) { - base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.base)); + if (encoding.hasBase()) { + base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); } append(new AArch64HotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -214,17 +230,28 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H // metaspace pointer Variable result = newVariable(LIRKind.value(AArch64Kind.QWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0) { - base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.base)); + if (encoding.hasBase()) { + base = emitLoadConstant(LIRKind.value(AArch64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); } append(new AArch64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; } } + @Override + public void emitNullCheck(Value address, LIRFrameState state) { + if (address.getValueKind().getPlatformKind() == AArch64Kind.DWORD) { + CompressEncoding encoding = config.getOopEncoding(); + Value uncompressed = emitUncompress(address, encoding, false); + append(new AArch64Move.NullCheckOp(asAddressValue(uncompressed), state)); + } else { + super.emitNullCheck(address, state); + } + } + @Override public void emitPrefetchAllocate(Value address) { - append(new AArch64PrefetchOp(asAddressValue(address), config.allocatePrefetchInstr)); + append(new AArch64PrefetchOp(asAddressValue(address), PrefetchMode.PSTL1KEEP)); } @Override @@ -294,8 +321,7 @@ public class AArch64HotSpotLIRGenerator extends AArch64LIRGenerator implements H LIRKind wordKind = LIRKind.value(target().arch.getWordKind()); RegisterValue thread = getProviders().getRegisters().getThreadRegister().asValue(wordKind); final int transferSize = value.getValueKind().getPlatformKind().getSizeInBytes(); - final int scaledDisplacement = offset >> NumUtil.log2Ceil(transferSize); - AArch64AddressValue address = new AArch64AddressValue(value.getValueKind(), thread, Value.ILLEGAL, scaledDisplacement, true, AddressingMode.IMMEDIATE_SCALED); + AArch64AddressValue address = new AArch64AddressValue(value.getValueKind(), thread, Value.ILLEGAL, offset, transferSize, AddressingMode.IMMEDIATE_SCALED); append(new StoreOp((AArch64Kind) value.getPlatformKind(), address, loadReg(value), null)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java index 8aa3a0483dc..ab0c674bdf5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.hotspot.aarch64; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -34,6 +35,7 @@ import org.graalvm.compiler.nodes.calc.FixedBinaryNode; import org.graalvm.compiler.nodes.calc.FloatConvertNode; import org.graalvm.compiler.nodes.calc.RemNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.aarch64.AArch64FloatArithmeticSnippets; import org.graalvm.compiler.replacements.aarch64.AArch64IntegerArithmeticSnippets; @@ -52,10 +54,10 @@ public class AArch64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvid } @Override - public void initialize(HotSpotProviders providers, GraalHotSpotVMConfig config) { - integerArithmeticSnippets = new AArch64IntegerArithmeticSnippets(providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - floatArithmeticSnippets = new AArch64FloatArithmeticSnippets(providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - super.initialize(providers, config); + public void initialize(OptionValues options, Iterable factories, HotSpotProviders providers, GraalHotSpotVMConfig config) { + integerArithmeticSnippets = new AArch64IntegerArithmeticSnippets(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); + floatArithmeticSnippets = new AArch64FloatArithmeticSnippets(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); + super.initialize(options, factories, providers, config); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java index 89dc03de43e..b0de7d96da3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMove.java @@ -22,16 +22,18 @@ */ package org.graalvm.compiler.hotspot.aarch64; +import static jdk.vm.ci.aarch64.AArch64.zr; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.code.ValueUtil.isRegister; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; -import static jdk.vm.ci.code.ValueUtil.asRegister; +import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; @@ -61,7 +63,7 @@ public class AArch64HotSpotMove { crb.recordInlineDataInCode(constant); if (constant.isCompressed()) { // masm.forceMov(asRegister(result), 0); - throw GraalError.unimplemented(); + masm.movNarrowAddress(asRegister(result), 0); } else { masm.movNativeAddress(asRegister(result), 0); } @@ -104,29 +106,26 @@ public class AArch64HotSpotMove { public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register resultRegister = asRegister(result); Register ptr = asRegister(input); - Register base = asRegister(baseRegister); + Register base = (isRegister(baseRegister) ? asRegister(baseRegister) : zr); // result = (ptr - base) >> shift - if (encoding.base == 0) { - if (encoding.shift == 0) { - masm.movx(resultRegister, ptr); + if (!encoding.hasBase()) { + if (encoding.hasShift()) { + masm.lshr(64, resultRegister, ptr, encoding.getShift()); } else { - assert encoding.alignment == encoding.shift : "Encode algorithm is wrong"; - masm.lshr(64, resultRegister, ptr, encoding.shift); + masm.movx(resultRegister, ptr); } } else if (nonNull) { masm.sub(64, resultRegister, ptr, base); - if (encoding.shift != 0) { - assert encoding.alignment == encoding.shift : "Encode algorithm is wrong"; - masm.shl(64, resultRegister, resultRegister, encoding.shift); + if (encoding.hasShift()) { + masm.shl(64, resultRegister, resultRegister, encoding.getShift()); } } else { // if ptr is null it still has to be null after compression masm.cmp(64, ptr, 0); masm.cmov(64, resultRegister, ptr, base, AArch64Assembler.ConditionFlag.NE); masm.sub(64, resultRegister, resultRegister, base); - if (encoding.shift != 0) { - assert encoding.alignment == encoding.shift : "Encode algorithm is wrong"; - masm.lshr(64, resultRegister, resultRegister, encoding.shift); + if (encoding.hasShift()) { + masm.lshr(64, resultRegister, resultRegister, encoding.getShift()); } } } @@ -158,17 +157,22 @@ public class AArch64HotSpotMove { public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register ptr = asRegister(input); Register resultRegister = asRegister(result); - Register base = asRegister(baseRegister); + Register base = (isRegister(baseRegister) ? asRegister(baseRegister) : zr); // result = base + (ptr << shift) if (nonNull) { - assert encoding.shift == encoding.alignment; - masm.add(64, resultRegister, base, ptr, AArch64Assembler.ShiftType.ASR, encoding.shift); + masm.add(64, resultRegister, base, ptr, AArch64Assembler.ShiftType.LSL, encoding.getShift()); + } else if (!encoding.hasBase()) { + masm.add(64, resultRegister, zr, ptr, AArch64Assembler.ShiftType.LSL, encoding.getShift()); } else { // if ptr is null it has to be null after decompression - // masm.cmp(64, ); - throw GraalError.unimplemented(); + Label done = new Label(); + if (!resultRegister.equals(ptr)) { + masm.mov(32, resultRegister, ptr); + } + masm.cbz(32, resultRegister, done); + masm.add(64, resultRegister, base, resultRegister, AArch64Assembler.ShiftType.LSL, encoding.getShift()); + masm.bind(done); } - } } @@ -188,10 +192,8 @@ public class AArch64HotSpotMove { public static void decodeKlassPointer(AArch64MacroAssembler masm, Register result, Register ptr, Register klassBase, CompressEncoding encoding) { // result = klassBase + ptr << shift - if (encoding.shift != 0 || encoding.base != 0) { - // (shift != 0 -> shift == alignment) - assert (encoding.shift == 0 || encoding.shift == encoding.alignment) : "Decode algorithm is wrong: " + encoding; - masm.add(64, result, klassBase, ptr, AArch64Assembler.ExtendType.UXTX, encoding.shift); + if (encoding.hasShift() || encoding.hasBase()) { + masm.add(64, result, klassBase, ptr, AArch64Assembler.ExtendType.UXTX, encoding.getShift()); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMoveFactory.java index 641cf5d8bd3..162de6d0f33 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotMoveFactory.java @@ -31,18 +31,18 @@ import org.graalvm.compiler.lir.LIRInstruction; import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; import jdk.vm.ci.hotspot.HotSpotConstant; +import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaConstant; public class AArch64HotSpotMoveFactory extends AArch64MoveFactory { @Override - public boolean canInlineConstant(JavaConstant c) { + public boolean canInlineConstant(Constant c) { if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { return true; - } else if (c instanceof HotSpotObjectConstant) { + } else if (c instanceof HotSpotObjectConstant || c instanceof HotSpotMetaspaceConstant) { return false; } else { return super.canInlineConstant(c); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java index 1352a913af2..07ea09963ea 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotNodeLIRBuilder.java @@ -22,30 +22,27 @@ */ package org.graalvm.compiler.hotspot.aarch64; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; import static jdk.vm.ci.aarch64.AArch64.lr; import static jdk.vm.ci.code.ValueUtil.isStackSlot; import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp; import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.inlineCacheRegister; import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.metaspaceMethodRegister; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; import org.graalvm.compiler.core.aarch64.AArch64NodeLIRBuilder; import org.graalvm.compiler.core.aarch64.AArch64NodeMatchRules; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.gen.DebugInfoBuilder; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.aarch64.AArch64BreakpointOp; -import org.graalvm.compiler.lir.aarch64.AArch64Move.CompareAndSwapOp; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.BreakpointNode; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; @@ -70,7 +67,6 @@ import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.Value; -import jdk.vm.ci.meta.ValueKind; /** * LIR generator specialized for AArch64 HotSpot. @@ -174,26 +170,12 @@ public class AArch64HotSpotNodeLIRBuilder extends AArch64NodeLIRBuilder implemen @Override public void visitFullInfopointNode(FullInfopointNode i) { if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { - Debug.log("Ignoring InfopointNode for AFTER_BCI"); + i.getDebug().log("Ignoring InfopointNode for AFTER_BCI"); } else { super.visitFullInfopointNode(i); } } - @Override - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - AllocatableValue address = gen.asAllocatable(operand(x.getAddress())); - AllocatableValue cmpValue = gen.asAllocatable(operand(x.expectedValue())); - AllocatableValue newValue = gen.asAllocatable(operand(x.newValue())); - ValueKind kind = cmpValue.getValueKind(); - assert kind.equals(newValue.getValueKind()); - - Variable result = gen.newVariable(newValue.getValueKind()); - Variable scratch = gen.newVariable(LIRKind.value(AArch64Kind.DWORD)); - append(new CompareAndSwapOp(result, cmpValue, newValue, address, scratch)); - setResult(x, result); - } - @Override public void visitBreakpointNode(BreakpointNode node) { JavaType[] sig = new JavaType[node.arguments().size()]; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotPatchReturnAddressOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotPatchReturnAddressOp.java index 5848b3bdda9..15e4e38ff8f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotPatchReturnAddressOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotPatchReturnAddressOp.java @@ -28,7 +28,6 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; -import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.AArch64ExceptionCode; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.aarch64.AArch64LIRInstruction; @@ -54,9 +53,9 @@ final class AArch64HotSpotPatchReturnAddressOp extends AArch64LIRInstruction { @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { final int frameSize = crb.frameMap.frameSize(); - // XXX where is lr exactly? - AArch64Address lrAddress = AArch64Address.createUnscaledImmediateAddress(sp, frameSize); - masm.brk(AArch64ExceptionCode.BREAKPOINT); // XXX + // LR is saved in the {fp, lr} pair above the frame + AArch64Address lrAddress = AArch64Address.createUnscaledImmediateAddress(sp, + frameSize + crb.target.wordSize); masm.str(64, asRegister(address), lrAddress); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java index ac9b0967dc5..d4013c5974e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java @@ -109,8 +109,8 @@ public class AArch64HotSpotRegisterAllocationConfig extends RegisterAllocationCo }; // @formatter:on - public AArch64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig) { - super(registerConfig); + public AArch64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { + super(registerConfig, allocationRestrictedTo); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java index 02b2146c36a..a2023faf776 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSafepointOp.java @@ -25,7 +25,7 @@ package org.graalvm.compiler.hotspot.aarch64; import static jdk.vm.ci.aarch64.AArch64.zr; import static jdk.vm.ci.code.ValueUtil.asRegister; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Address; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -77,18 +77,18 @@ public class AArch64HotSpotSafepointOp extends AArch64LIRInstruction { } public static void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm, GraalHotSpotVMConfig config, boolean onReturn, Register scratch, LIRFrameState state) { - int pos = masm.position(); if (isPollingPageFar(config)) { crb.recordMark(onReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR); masm.movNativeAddress(scratch, config.safepointPollingAddress); + crb.recordMark(onReturn ? config.MARKID_POLL_RETURN_FAR : config.MARKID_POLL_FAR); if (state != null) { - crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); + crb.recordInfopoint(masm.position(), state, InfopointReason.SAFEPOINT); } masm.ldr(32, zr, AArch64Address.createBaseRegisterOnlyAddress(scratch)); } else { crb.recordMark(onReturn ? config.MARKID_POLL_RETURN_NEAR : config.MARKID_POLL_NEAR); if (state != null) { - crb.recordInfopoint(pos, state, InfopointReason.SAFEPOINT); + crb.recordInfopoint(masm.position(), state, InfopointReason.SAFEPOINT); } masm.ldr(32, zr, AArch64Address.createPcLiteralAddress(0)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSuitesProvider.java new file mode 100644 index 00000000000..41ab1423bcf --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSuitesProvider.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.aarch64; + +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; +import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.BasePhase; +import org.graalvm.compiler.phases.common.AddressLoweringByUsePhase; +import org.graalvm.compiler.phases.common.ExpandLogicPhase; +import org.graalvm.compiler.phases.common.FixReadsPhase; +import org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase; +import org.graalvm.compiler.phases.tiers.LowTierContext; +import org.graalvm.compiler.phases.tiers.Suites; +import org.graalvm.compiler.phases.tiers.SuitesCreator; +import org.graalvm.compiler.replacements.aarch64.AArch64ReadReplacementPhase; + +import java.util.ListIterator; + +/** + * Subclass to factor out management of address lowering. + */ +public class AArch64HotSpotSuitesProvider extends HotSpotSuitesProvider { + + private final AddressLoweringByUsePhase.AddressLoweringByUse addressLoweringByUse; + + public AArch64HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, + AddressLoweringByUsePhase.AddressLoweringByUse addressLoweringByUse) { + super(defaultSuitesCreator, config, runtime); + this.addressLoweringByUse = addressLoweringByUse; + } + + @Override + public Suites createSuites(OptionValues options) { + Suites suites = super.createSuites(options); + + ListIterator> findPhase = suites.getLowTier().findPhase(FixReadsPhase.class); + if (findPhase == null) { + findPhase = suites.getLowTier().findPhase(ExpandLogicPhase.class); + } + findPhase.add(new AddressLoweringByUsePhase(addressLoweringByUse)); + + findPhase = suites.getLowTier().findPhase(PropagateDeoptimizeProbabilityPhase.class); + findPhase.add(new AArch64ReadReplacementPhase()); + + return suites; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64RawNativeCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64RawNativeCallNode.java new file mode 100644 index 00000000000..1bd87780929 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64RawNativeCallNode.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.aarch64; + +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; + +import org.graalvm.compiler.core.aarch64.AArch64NodeLIRBuilder; +import org.graalvm.compiler.core.common.type.RawPointerStamp; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.NodeInputList; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.spi.LIRLowerable; +import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; + +import jdk.vm.ci.code.CallingConvention; +import jdk.vm.ci.hotspot.HotSpotCallingConventionType; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Value; + +@NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "Native call is a block hole", size = SIZE_UNKNOWN) +public final class AArch64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(AArch64RawNativeCallNode.class); + + protected final JavaConstant functionPointer; + @Input NodeInputList args; + + public AArch64RawNativeCallNode(JavaKind returnType, JavaConstant functionPointer, ValueNode[] args) { + super(TYPE, StampFactory.forKind(returnType)); + this.functionPointer = functionPointer; + this.args = new NodeInputList<>(this, args); + } + + private static class PointerType implements JavaType { + + @Override + public String getName() { + return "void*"; + } + + @Override + public JavaType getComponentType() { + return null; + } + + @Override + public JavaType getArrayClass() { + return null; + } + + @Override + public JavaKind getJavaKind() { + // native pointers and java objects use the same registers in the calling convention + return JavaKind.Object; + } + + @Override + public ResolvedJavaType resolve(ResolvedJavaType accessingClass) { + return null; + } + } + + private static JavaType toJavaType(Stamp stamp, MetaAccessProvider metaAccess) { + if (stamp instanceof RawPointerStamp) { + return new PointerType(); + } else { + return stamp.javaType(metaAccess); + } + } + + @Override + public void generate(NodeLIRBuilderTool generator) { + AArch64NodeLIRBuilder gen = (AArch64NodeLIRBuilder) generator; + Value[] parameter = new Value[args.count()]; + JavaType[] parameterTypes = new JavaType[args.count()]; + for (int i = 0; i < args.count(); i++) { + parameter[i] = generator.operand(args.get(i)); + parameterTypes[i] = toJavaType(args.get(i).stamp(), gen.getLIRGeneratorTool().getMetaAccess()); + } + JavaType returnType = toJavaType(stamp(), gen.getLIRGeneratorTool().getMetaAccess()); + CallingConvention cc = generator.getLIRGeneratorTool().getCodeCache().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.NativeCall, returnType, parameterTypes, + generator.getLIRGeneratorTool()); + gen.getLIRGeneratorTool().emitCCall(functionPointer.asLong(), cc, parameter); + if (this.getStackKind() != JavaKind.Void) { + generator.setResult(this, gen.getLIRGeneratorTool().emitMove(cc.getReturn())); + } + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/CompressedNullCheckTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/CompressedNullCheckTest.java index 31b67987d9e..706b1fd36d2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/CompressedNullCheckTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/CompressedNullCheckTest.java @@ -22,19 +22,13 @@ */ package org.graalvm.compiler.hotspot.amd64.test; -import org.junit.Assert; +import static org.graalvm.compiler.core.common.GraalOptions.OptImplicitNullChecks; + +import org.graalvm.compiler.hotspot.test.HotSpotGraalCompilerTest; +import org.graalvm.compiler.options.OptionValues; import org.junit.Assume; import org.junit.Test; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; -import org.graalvm.compiler.hotspot.test.HotSpotGraalCompilerTest; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.IsNullNode; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - import jdk.vm.ci.meta.ResolvedJavaMethod; /** @@ -57,16 +51,15 @@ public class CompressedNullCheckTest extends HotSpotGraalCompilerTest { Container c = new Container(); c.i = i; - try (OverrideScope s = OptionValue.override(GraalOptions.OptImplicitNullChecks, true)) { - ResolvedJavaMethod method = getResolvedJavaMethod("testSnippet"); - Result expect = executeExpected(method, null, c); + ResolvedJavaMethod method = getResolvedJavaMethod("testSnippet"); + Result expect = executeExpected(method, null, c); - // make sure we don't get a profile that removes the implicit null check - method.reprofile(); + // make sure we don't get a profile that removes the implicit null check + method.reprofile(); - Result actual = executeActual(method, null, c); - assertEquals(expect, actual); - } + OptionValues options = new OptionValues(getInitialOptions(), OptImplicitNullChecks, true); + Result actual = executeActual(options, method, null, c); + assertEquals(expect, actual); } @SuppressWarnings("try") @@ -76,9 +69,7 @@ public class CompressedNullCheckTest extends HotSpotGraalCompilerTest { Container c = new Container(); c.i = i; - try (OverrideScope s = OptionValue.override(GraalOptions.OptImplicitNullChecks, false)) { - test("testSnippet", c); - } + test(new OptionValues(getInitialOptions(), OptImplicitNullChecks, false), "testSnippet", c); } @Test @@ -100,18 +91,4 @@ public class CompressedNullCheckTest extends HotSpotGraalCompilerTest { public void explicitNull() { testExplicit(null); } - - @Override - protected boolean checkMidTierGraph(StructuredGraph graph) { - int count = 0; - for (IsNullNode isNull : graph.getNodes().filter(IsNullNode.class).snapshot()) { - ValueNode value = isNull.getValue(); - if (value instanceof CompressionNode) { - count++; - isNull.replaceFirstInput(value, ((CompressionNode) value).getValue()); - } - } - Assert.assertEquals("graph should contain exactly one IsNullNode", 1, count); - return super.checkMidTierGraph(graph); - } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/DataPatchInConstantsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/DataPatchInConstantsTest.java index 3c83cc47b11..4d1adff918e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/DataPatchInConstantsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/DataPatchInConstantsTest.java @@ -23,20 +23,15 @@ package org.graalvm.compiler.hotspot.amd64.test; +import static jdk.vm.ci.code.ValueUtil.asRegister; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; -import static jdk.vm.ci.code.ValueUtil.asRegister; - -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; -import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp; +import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode; import org.graalvm.compiler.hotspot.test.HotSpotGraalCompilerTest; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; @@ -46,12 +41,16 @@ import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.nodes.type.NarrowOopStamp; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.meta.AllocatableValue; @@ -141,9 +140,8 @@ public class DataPatchInConstantsTest extends HotSpotGraalCompilerTest { } @Override - protected Plugins getDefaultGraphBuilderPlugins() { - Plugins plugins = super.getDefaultGraphBuilderPlugins(); - Registration r = new Registration(plugins.getInvocationPlugins(), DataPatchInConstantsTest.class); + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { + Registration r = new Registration(invocationPlugins, DataPatchInConstantsTest.class); r.register1("loadThroughPatch", Object.class, new InvocationPlugin() { @Override @@ -156,14 +154,13 @@ public class DataPatchInConstantsTest extends HotSpotGraalCompilerTest { r.register1("loadThroughCompressedPatch", Object.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { - ValueNode compressed = b.add(CompressionNode.compress(arg, runtime().getVMConfig().getOopEncoding())); + ValueNode compressed = b.add(HotSpotCompressionNode.compress(arg, runtime().getVMConfig().getOopEncoding())); ValueNode patch = b.add(new LoadThroughPatchNode(compressed)); - b.addPush(JavaKind.Object, CompressionNode.uncompress(patch, runtime().getVMConfig().getOopEncoding())); + b.addPush(JavaKind.Object, HotSpotCompressionNode.uncompress(patch, runtime().getVMConfig().getOopEncoding())); return true; } }); - - return plugins; + super.registerInvocationPlugins(invocationPlugins); } @NodeInfo(cycles = CYCLES_2, size = SIZE_1) diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java index b7b473b8b47..b72925f67eb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64.test/src/org/graalvm/compiler/hotspot/amd64/test/StubAVXTest.java @@ -25,13 +25,10 @@ package org.graalvm.compiler.hotspot.amd64.test; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; - import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.DataPointerConstant; @@ -52,6 +49,12 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.replacements.ReplacementsImpl; +import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64.CPUFeature; @@ -59,6 +62,7 @@ import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.ValueUtil; import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.Value; @@ -163,13 +167,20 @@ public class StubAVXTest extends LIRTest { private static class TestStub extends SnippetStub { - TestStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("testStub", providers, linkage); + TestStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("testStub", options, providers, linkage); } @Snippet static void testStub() { } + + @Override + protected BytecodeProvider getReplacementsBytecodeProvider() { + ReplacementsImpl d = (ReplacementsImpl) providers.getReplacements(); + MetaAccessProvider metaAccess = d.providers.getMetaAccess(); + return new ClassfileBytecodeProvider(metaAccess, d.snippetReflection, ClassLoader.getSystemClassLoader()); + } } public static final ForeignCallDescriptor TEST_STUB = new ForeignCallDescriptor("test_stub", void.class); @@ -208,7 +219,7 @@ public class StubAVXTest extends LIRTest { HotSpotProviders providers = (HotSpotProviders) getProviders(); HotSpotForeignCallsProviderImpl foreignCalls = (HotSpotForeignCallsProviderImpl) providers.getForeignCalls(); HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, true, HotSpotForeignCallLinkage.Transition.LEAF_NOFP); - linkage.setCompiledStub(new TestStub(providers, linkage)); + linkage.setCompiledStub(new TestStub(getInitialOptions(), providers, linkage)); runTest("testStub"); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64DeoptimizationStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64DeoptimizationStub.java deleted file mode 100644 index d0d77efd99b..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64DeoptimizationStub.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.amd64; - -import static jdk.vm.ci.amd64.AMD64.r10; -import static jdk.vm.ci.amd64.AMD64.r11; -import static jdk.vm.ci.amd64.AMD64.r13; -import static jdk.vm.ci.amd64.AMD64.r14; -import static jdk.vm.ci.amd64.AMD64.r8; -import static jdk.vm.ci.amd64.AMD64.r9; -import static jdk.vm.ci.amd64.AMD64.rbx; -import static jdk.vm.ci.amd64.AMD64.rcx; -import static jdk.vm.ci.amd64.AMD64.rdi; -import static jdk.vm.ci.amd64.AMD64.rdx; -import static jdk.vm.ci.amd64.AMD64.rsi; - -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.DeoptimizationStub; - -import jdk.vm.ci.code.RegisterArray; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.amd64.AMD64HotSpotRegisterConfig; - -final class AMD64DeoptimizationStub extends DeoptimizationStub { - - private RegisterConfig registerConfig; - - AMD64DeoptimizationStub(HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); - registerConfig = new AMD64HotSpotRegisterConfig(target, new RegisterArray(rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r13, r14), config.windowsOs); - } - - @Override - public RegisterConfig getRegisterConfig() { - return registerConfig; - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java index d8c5cd6227a..a26ed27391c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,34 +27,40 @@ import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; -import org.graalvm.compiler.asm.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.amd64.AMD64AddressLowering; import org.graalvm.compiler.core.amd64.AMD64AddressNode; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; -import org.graalvm.compiler.hotspot.nodes.CompressionNode.CompressionOp; import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.CompressionNode; +import org.graalvm.compiler.nodes.CompressionNode.CompressionOp; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.JavaKind; public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { + private static final CounterKey counterFoldedUncompressDuringAddressLowering = DebugContext.counter("FoldedUncompressDuringAddressLowering"); + private final long heapBase; private final Register heapBaseRegister; private final GraalHotSpotVMConfig config; + private final boolean generatePIC; @NodeInfo(cycles = CYCLES_0, size = SIZE_0) public static class HeapBaseNode extends FloatingNode implements LIRLowerable { @@ -75,10 +81,11 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { } } - public AMD64HotSpotAddressLowering(GraalHotSpotVMConfig config, Register heapBaseRegister) { - this.heapBase = config.getOopEncoding().base; + public AMD64HotSpotAddressLowering(GraalHotSpotVMConfig config, Register heapBaseRegister, OptionValues options) { + this.heapBase = config.getOopEncoding().getBase(); this.config = config; - if (heapBase == 0 && !GeneratePIC.getValue()) { + this.generatePIC = GeneratePIC.getValue(options); + if (heapBase == 0 && !generatePIC) { this.heapBaseRegister = null; } else { this.heapBaseRegister = heapBaseRegister; @@ -86,34 +93,43 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { } @Override - protected boolean improve(AMD64AddressNode addr) { + protected boolean improve(DebugContext debug, AMD64AddressNode addr) { + + boolean result = false; + + while (super.improve(debug, addr)) { + result = true; + } + if (addr.getScale() == Scale.Times1) { - if (addr.getBase() == null && addr.getIndex() instanceof CompressionNode) { - if (improveUncompression(addr, (CompressionNode) addr.getIndex())) { + if (addr.getIndex() instanceof CompressionNode) { + if (improveUncompression(addr, (CompressionNode) addr.getIndex(), addr.getBase())) { + counterFoldedUncompressDuringAddressLowering.increment(debug); return true; } } - if (addr.getIndex() == null && addr.getBase() instanceof CompressionNode) { - if (improveUncompression(addr, (CompressionNode) addr.getBase())) { + if (addr.getBase() instanceof CompressionNode) { + if (improveUncompression(addr, (CompressionNode) addr.getBase(), addr.getIndex())) { + counterFoldedUncompressDuringAddressLowering.increment(debug); return true; } } } - return super.improve(addr); + return result; } - private boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression) { + private boolean improveUncompression(AMD64AddressNode addr, CompressionNode compression, ValueNode other) { if (compression.getOp() == CompressionOp.Uncompress) { CompressEncoding encoding = compression.getEncoding(); - Scale scale = Scale.fromShift(encoding.shift); + Scale scale = Scale.fromShift(encoding.getShift()); if (scale == null) { return false; } - if (heapBaseRegister != null && encoding.base == heapBase) { - if (!GeneratePIC.getValue() || compression.stamp() instanceof ObjectStamp) { + if (heapBaseRegister != null && encoding.getBase() == heapBase) { + if ((!generatePIC || compression.stamp() instanceof ObjectStamp) && other == null) { // With PIC it is only legal to do for oops since the base value may be // different at runtime. ValueNode base = compression.graph().unique(new HeapBaseNode(heapBaseRegister)); @@ -121,21 +137,25 @@ public class AMD64HotSpotAddressLowering extends AMD64AddressLowering { } else { return false; } - } else if (encoding.base != 0 || (GeneratePIC.getValue() && compression.stamp() instanceof KlassPointerStamp)) { - if (GeneratePIC.getValue()) { - ValueNode base = compression.graph().unique(new GraalHotSpotVMConfigNode(config, config.MARKID_NARROW_KLASS_BASE_ADDRESS, JavaKind.Long)); - addr.setBase(base); + } else if (encoding.getBase() != 0 || (generatePIC && compression.stamp() instanceof KlassPointerStamp)) { + if (generatePIC) { + if (other == null) { + ValueNode base = compression.graph().unique(new GraalHotSpotVMConfigNode(config, config.MARKID_NARROW_KLASS_BASE_ADDRESS, JavaKind.Long)); + addr.setBase(base); + } else { + return false; + } } else { - long disp = addr.getDisplacement() + encoding.base; + long disp = addr.getDisplacement() + encoding.getBase(); if (NumUtil.isInt(disp)) { addr.setDisplacement((int) disp); - addr.setBase(null); + addr.setBase(other); } else { return false; } } } else { - addr.setBase(null); + addr.setBase(other); } addr.setScale(scale); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotArithmeticLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotArithmeticLIRGenerator.java index b14f17795be..3e011324fd1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotArithmeticLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotArithmeticLIRGenerator.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.hotspot.amd64; +import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.COS; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG10; @@ -31,7 +32,6 @@ import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.Int import org.graalvm.compiler.core.amd64.AMD64ArithmeticLIRGenerator; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.lir.Variable; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import jdk.vm.ci.meta.Value; @@ -39,7 +39,7 @@ public class AMD64HotSpotArithmeticLIRGenerator extends AMD64ArithmeticLIRGenera @Override public Value emitMathLog(Value input, boolean base10) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(getOptions())) { return super.emitMathLog(input, base10); } Variable result = getLIRGen().newVariable(LIRKind.combine(input)); @@ -49,7 +49,7 @@ public class AMD64HotSpotArithmeticLIRGenerator extends AMD64ArithmeticLIRGenera @Override public Value emitMathCos(Value input) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(getOptions())) { return super.emitMathCos(input); } Variable result = getLIRGen().newVariable(LIRKind.combine(input)); @@ -59,7 +59,7 @@ public class AMD64HotSpotArithmeticLIRGenerator extends AMD64ArithmeticLIRGenera @Override public Value emitMathSin(Value input) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(getOptions())) { return super.emitMathSin(input); } Variable result = getLIRGen().newVariable(LIRKind.combine(input)); @@ -69,7 +69,7 @@ public class AMD64HotSpotArithmeticLIRGenerator extends AMD64ArithmeticLIRGenera @Override public Value emitMathTan(Value input) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(getOptions())) { return super.emitMathTan(input); } Variable result = getLIRGen().newVariable(LIRKind.combine(input)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java index 7cb4b03b27e..692c444058e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java @@ -22,15 +22,13 @@ */ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.core.common.GraalOptions.CanOmitFrame; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; import static jdk.vm.ci.amd64.AMD64.r10; import static jdk.vm.ci.amd64.AMD64.rax; import static jdk.vm.ci.amd64.AMD64.rsp; import static jdk.vm.ci.code.ValueUtil.asRegister; - -import java.util.Set; +import static org.graalvm.compiler.core.common.GraalOptions.CanOmitFrame; +import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Label; @@ -39,10 +37,11 @@ import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.amd64.AMD64NodeMatchRules; -import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.target.Backend; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotDataBuilder; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; @@ -66,6 +65,8 @@ import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64Kind; @@ -170,7 +171,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { } else { asm.decrementq(rsp, frameSize); } - if (ZapStackOnMethodEntry.getValue()) { + if (ZapStackOnMethodEntry.getValue(crb.getOptions())) { final int intSize = 4; for (int i = 0; i < frameSize / intSize; ++i) { asm.movl(new AMD64Address(rsp, i * intSize), 0xC1C1C1C1); @@ -208,13 +209,15 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { HotSpotLIRGenerationResult gen = (HotSpotLIRGenerationResult) lirGenRen; LIR lir = gen.getLIR(); assert gen.getDeoptimizationRescueSlot() == null || frameMap.frameNeedsAllocating() : "method that can deoptimize must have a frame"; - boolean omitFrame = CanOmitFrame.getValue() && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall(); + OptionValues options = lir.getOptions(); + DebugContext debug = lir.getDebug(); + boolean omitFrame = CanOmitFrame.getValue(options) && !frameMap.frameNeedsAllocating() && !lir.hasArgInCallerFrame() && !gen.hasForeignCall(); Stub stub = gen.getStub(); Assembler masm = createAssembler(frameMap); HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); - CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, compilationResult); + CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, debug, compilationResult); crb.setTotalFrameSize(frameMap.totalFrameSize()); crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); @@ -223,7 +226,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { } if (stub != null) { - Set destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); + EconomicSet destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); updateStub(stub, destroyedCallerRegisters, gen.getCalleeSaveInfo(), frameMap); } @@ -268,7 +271,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { if (config.useCompressedClassPointers) { Register register = r10; AMD64HotSpotMove.decodeKlassPointer(crb, asm, register, providers.getRegisters().getHeapBaseRegister(), src, config); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { asm.movq(providers.getRegisters().getHeapBaseRegister(), asm.getPlaceholder(-1)); crb.recordMark(config.MARKID_NARROW_OOP_BASE_ADDRESS); } else { @@ -289,7 +292,7 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { asm.bind(verifiedEntry); crb.recordMark(config.MARKID_VERIFIED_ENTRY); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { // Check for method state HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext; if (!frameContext.isStub) { @@ -334,13 +337,13 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend { } @Override - public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig) { + public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; - return new AMD64HotSpotRegisterAllocationConfig(registerConfigNonNull); + return new AMD64HotSpotRegisterAllocationConfig(registerConfigNonNull, allocationRestrictedTo); } @Override - public Set translateToCallerRegisters(Set calleeRegisters) { + public EconomicSet translateToCallerRegisters(EconomicSet calleeRegisters) { return calleeRegisters; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java index 96f90d0d7fe..ed56a74213b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java @@ -22,9 +22,8 @@ */ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import static jdk.vm.ci.common.InitTimer.timer; - +import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import java.util.ArrayList; import java.util.List; @@ -36,6 +35,7 @@ import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotBackendFactory; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotReplacementsImpl; +import org.graalvm.compiler.hotspot.meta.AddressLoweringHotSpotSuitesProvider; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider; import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins; @@ -47,11 +47,10 @@ import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSnippetReflectionProvider; import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider; -import org.graalvm.compiler.hotspot.nodes.HotSpotNodeCostProvider; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; -import org.graalvm.compiler.nodes.spi.NodeCostProvider; import org.graalvm.compiler.nodes.spi.Replacements; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.replacements.amd64.AMD64GraphBuilderPlugins; @@ -90,6 +89,7 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { public HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotBackend host) { assert host == null; + OptionValues options = graalRuntime.getOptions(); JVMCIBackend jvmci = jvmciRuntime.getHostJVMCIBackend(); GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); HotSpotProviders providers; @@ -107,7 +107,6 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { HotSpotSuitesProvider suites; HotSpotWordTypes wordTypes; Plugins plugins; - NodeCostProvider nodeCostProvider; BytecodeProvider bytecodeProvider; try (InitTimer t = timer("create providers")) { try (InitTimer rt = timer("create HotSpotRegisters provider")) { @@ -125,11 +124,8 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { try (InitTimer rt = timer("create Lowerer provider")) { lowerer = createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, target); } - try (InitTimer rt = timer("create NodeCost provider")) { - nodeCostProvider = createNodeCostProvider(target); - } HotSpotStampProvider stampProvider = new HotSpotStampProvider(); - Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, nodeCostProvider); + Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider); try (InitTimer rt = timer("create SnippetReflection provider")) { snippetReflection = createSnippetReflection(graalRuntime, constantReflection, wordTypes); @@ -138,16 +134,17 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection); } try (InitTimer rt = timer("create Replacements provider")) { - replacements = createReplacements(p, snippetReflection, bytecodeProvider); + replacements = createReplacements(options, p, snippetReflection, bytecodeProvider); } try (InitTimer rt = timer("create GraphBuilderPhase plugins")) { - plugins = createGraphBuilderPlugins(config, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, stampProvider); + plugins = createGraphBuilderPlugins(compilerConfiguration, config, options, target, constantReflection, foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, + stampProvider); replacements.setGraphBuilderPlugins(plugins); } try (InitTimer rt = timer("create Suites provider")) { - suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, registers, replacements); + suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, registers, replacements, options); } - providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, nodeCostProvider, suites, registers, + providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, snippetReflection, wordTypes, plugins); } @@ -156,12 +153,11 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { } } - protected Plugins createGraphBuilderPlugins(GraalHotSpotVMConfig config, TargetDescription target, HotSpotConstantReflectionProvider constantReflection, - HotSpotHostForeignCallsProvider foreignCalls, - HotSpotMetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, - HotSpotStampProvider stampProvider) { - Plugins plugins = HotSpotGraphBuilderPlugins.create(config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); - AMD64GraphBuilderPlugins.register(plugins, replacements.getReplacementBytecodeProvider(), (AMD64) target.arch, GraalArithmeticStubs.getValue()); + protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, OptionValues options, TargetDescription target, + HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess, + HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, HotSpotStampProvider stampProvider) { + Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); + AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, GraalArithmeticStubs.getValue(options)); return plugins; } @@ -173,8 +169,8 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { return new HotSpotRegisters(AMD64.r15, AMD64.r12, AMD64.rsp); } - protected HotSpotReplacementsImpl createReplacements(Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { - return new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); + protected HotSpotReplacementsImpl createReplacements(OptionValues options, Providers p, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider) { + return new HotSpotReplacementsImpl(options, p, snippetReflection, bytecodeProvider, p.getCodeCache().getTarget()); } protected AMD64HotSpotForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider runtime, HotSpotMetaAccessProvider metaAccess, @@ -186,8 +182,9 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { * @param replacements */ protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins, - HotSpotRegistersProvider registers, Replacements replacements) { - return new HotSpotSuitesProvider(new AMD64HotSpotSuitesProvider(compilerConfiguration, plugins), config, runtime, new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister())); + HotSpotRegistersProvider registers, Replacements replacements, OptionValues options) { + return new AddressLoweringHotSpotSuitesProvider(new AMD64HotSpotSuitesCreator(compilerConfiguration, plugins), config, runtime, + new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister(), options)); } protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) { @@ -199,10 +196,6 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory { return new AMD64HotSpotLoweringProvider(runtime, metaAccess, foreignCalls, registers, constantReflection, target); } - protected HotSpotNodeCostProvider createNodeCostProvider(TargetDescription target) { - return new AMD64HotSpotNodeCostProvider(target); - } - protected Value[] createNativeABICallerSaveRegisters(GraalHotSpotVMConfig config, RegisterConfig regConfig) { List callerSave = new ArrayList<>(regConfig.getAllocatableRegisters().asList()); if (config.windowsOs) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java deleted file mode 100644 index 30c8a7f07ee..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.amd64; - -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import static jdk.vm.ci.amd64.AMD64.rax; -import static jdk.vm.ci.amd64.AMD64.rbp; -import static jdk.vm.ci.amd64.AMD64.rip; -import static jdk.vm.ci.code.ValueUtil.asRegister; - -import org.graalvm.compiler.asm.amd64.AMD64Address; -import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.Opcode; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.framemap.FrameMap; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.RegisterSaveLayout; -import jdk.vm.ci.meta.AllocatableValue; -import jdk.vm.ci.meta.JavaKind; - -/** - * Emits code that enters a stack frame which is tailored to call the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME") -final class AMD64HotSpotEnterUnpackFramesStackFrameOp extends AMD64LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotEnterUnpackFramesStackFrameOp.class); - - private final Register threadRegister; - private final int threadLastJavaSpOffset; - private final int threadLastJavaPcOffset; - private final int threadLastJavaFpOffset; - @Alive(REG) AllocatableValue framePc; - @Alive(REG) AllocatableValue senderSp; - @Alive(REG) AllocatableValue senderFp; - - private final SaveRegistersOp saveRegisterOp; - - AMD64HotSpotEnterUnpackFramesStackFrameOp(Register threadRegister, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, AllocatableValue framePc, - AllocatableValue senderSp, AllocatableValue senderFp, SaveRegistersOp saveRegisterOp) { - super(TYPE); - this.threadRegister = threadRegister; - this.threadLastJavaSpOffset = threadLastJavaSpOffset; - this.threadLastJavaPcOffset = threadLastJavaPcOffset; - this.threadLastJavaFpOffset = threadLastJavaFpOffset; - this.framePc = framePc; - this.senderSp = senderSp; - this.senderFp = senderFp; - this.saveRegisterOp = saveRegisterOp; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - FrameMap frameMap = crb.frameMap; - RegisterConfig registerConfig = frameMap.getRegisterConfig(); - RegisterSaveLayout registerSaveLayout = saveRegisterOp.getMap(frameMap); - Register stackPointerRegister = registerConfig.getFrameRegister(); - final int totalFrameSize = frameMap.totalFrameSize(); - - // Push return address. - masm.push(asRegister(framePc)); - - // Push base pointer. - masm.push(asRegister(senderFp)); - masm.movq(rbp, stackPointerRegister); - - /* - * Allocate a full sized frame. Since return address and base pointer are already in place - * (see above) we allocate two words less. - */ - masm.decrementq(stackPointerRegister, totalFrameSize - 2 * crb.target.wordSize); - - // Save return registers after moving the frame. - final int stackSlotSize = frameMap.getTarget().wordSize; - Register integerResultRegister = registerConfig.getReturnRegister(JavaKind.Long); - masm.movptr(new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(integerResultRegister) * stackSlotSize), integerResultRegister); - - Register floatResultRegister = registerConfig.getReturnRegister(JavaKind.Double); - masm.movdbl(new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(floatResultRegister) * stackSlotSize), floatResultRegister); - - // Set up last Java values. - masm.movq(new AMD64Address(threadRegister, threadLastJavaSpOffset), stackPointerRegister); - - /* - * Save the PC since it cannot easily be retrieved using the last Java SP after we aligned - * SP. Don't need the precise return PC here, just precise enough to point into this code - * blob. - */ - masm.leaq(rax, new AMD64Address(rip, 0)); - masm.movq(new AMD64Address(threadRegister, threadLastJavaPcOffset), rax); - - // Use BP because the frames look interpreted now. - masm.movq(new AMD64Address(threadRegister, threadLastJavaFpOffset), rbp); - - // Align the stack for the following unpackFrames call. - masm.andq(stackPointerRegister, -(crb.target.stackAlignment)); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java index 3f9f2cded39..e92e17485dc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java @@ -22,21 +22,18 @@ */ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.core.common.LocationIdentity.any; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; -import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPTIMIZATION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER; -import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import static jdk.vm.ci.amd64.AMD64.rax; import static jdk.vm.ci.amd64.AMD64.rdx; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static jdk.vm.ci.meta.Value.ILLEGAL; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; +import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; +import static org.graalvm.word.LocationIdentity.any; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; @@ -45,6 +42,7 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.WordTypes; import jdk.vm.ci.code.CallingConvention; @@ -75,7 +73,7 @@ public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro } @Override - public void initialize(HotSpotProviders providers) { + public void initialize(HotSpotProviders providers, OptionValues options) { GraalHotSpotVMConfig config = runtime.getVMConfig(); TargetDescription target = providers.getCodeCache().getTarget(); PlatformKind word = target.arch.getWordKind(); @@ -89,24 +87,20 @@ public class AMD64HotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, exceptionCc, null, NOT_REEXECUTABLE, any())); register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, exceptionCc, null, NOT_REEXECUTABLE, any())); - if (PreferGraalStubs.getValue()) { - link(new AMD64DeoptimizationStub(providers, target, config, registerStubCall(DEOPTIMIZATION_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64UncommonTrapStub(providers, target, config, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); - } - link(new AMD64MathStub(ARITHMETIC_LOG_STUB, providers, registerStubCall(ARITHMETIC_LOG_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_LOG10_STUB, providers, registerStubCall(ARITHMETIC_LOG10_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_SIN_STUB, providers, registerStubCall(ARITHMETIC_SIN_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_COS_STUB, providers, registerStubCall(ARITHMETIC_COS_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_TAN_STUB, providers, registerStubCall(ARITHMETIC_TAN_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_EXP_STUB, providers, registerStubCall(ARITHMETIC_EXP_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new AMD64MathStub(ARITHMETIC_POW_STUB, providers, registerStubCall(ARITHMETIC_POW_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_LOG_STUB, options, providers, registerStubCall(ARITHMETIC_LOG_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_LOG10_STUB, options, providers, registerStubCall(ARITHMETIC_LOG10_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_SIN_STUB, options, providers, registerStubCall(ARITHMETIC_SIN_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_COS_STUB, options, providers, registerStubCall(ARITHMETIC_COS_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_TAN_STUB, options, providers, registerStubCall(ARITHMETIC_TAN_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_EXP_STUB, options, providers, registerStubCall(ARITHMETIC_EXP_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); + link(new AMD64MathStub(ARITHMETIC_POW_STUB, options, providers, registerStubCall(ARITHMETIC_POW_STUB, REEXECUTABLE, LEAF, NO_LOCATIONS))); if (config.useCRC32Intrinsics) { // This stub does callee saving registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any()); } - super.initialize(providers); + super.initialize(providers, options); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java index bd87349a2d4..0fb58738803 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java @@ -22,29 +22,27 @@ */ package org.graalvm.compiler.hotspot.amd64; +import static jdk.vm.ci.amd64.AMD64.rbp; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; -import static org.graalvm.compiler.hotspot.HotSpotBackend.FETCH_UNROLL_INFO; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNCOMMON_TRAP; -import static jdk.vm.ci.amd64.AMD64.rbp; import java.util.ArrayList; import java.util.List; -import java.util.Map; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.core.amd64.AMD64ArithmeticLIRGenerator; import org.graalvm.compiler.core.amd64.AMD64LIRGenerator; +import org.graalvm.compiler.core.amd64.AMD64LIRKindTool; import org.graalvm.compiler.core.amd64.AMD64MoveFactoryBase.BackupSlotProvider; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.LIRKindTool; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; @@ -55,7 +53,6 @@ import org.graalvm.compiler.hotspot.HotSpotLockStack; import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.type.HotSpotLIRKindTool; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRFrameState; @@ -63,7 +60,6 @@ import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.LabelRef; import org.graalvm.compiler.lir.StandardOp.NoOp; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.SwitchStrategy; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.VirtualStackSlot; @@ -81,6 +77,7 @@ import org.graalvm.compiler.lir.amd64.AMD64VZeroUpper; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; import org.graalvm.compiler.lir.gen.LIRGenerationResult; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64Kind; @@ -114,7 +111,7 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp } private AMD64HotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, BackupSlotProvider backupSlotProvider) { - this(new AMD64HotSpotLIRKindTool(), new AMD64HotSpotArithmeticLIRGenerator(), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes); + this(new AMD64LIRKindTool(), new AMD64HotSpotArithmeticLIRGenerator(), new AMD64HotSpotMoveFactory(backupSlotProvider), providers, config, lirGenRes); } protected AMD64HotSpotLIRGenerator(LIRKindTool lirKindTool, AMD64ArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config, @@ -294,34 +291,6 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp super.emitForeignCallOp(linkage, result, arguments, temps, info); } - @Override - public void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) { - append(new AMD64HotSpotLeaveCurrentStackFrameOp(saveRegisterOp)); - } - - @Override - public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { - Variable frameSizeVariable = load(frameSize); - Variable initialInfoVariable = load(initialInfo); - append(new AMD64HotSpotLeaveDeoptimizedStackFrameOp(frameSizeVariable, initialInfoVariable)); - } - - @Override - public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp, SaveRegistersOp saveRegisterOp) { - Register threadRegister = getProviders().getRegisters().getThreadRegister(); - Variable framePcVariable = load(framePc); - Variable senderSpVariable = load(senderSp); - Variable senderFpVariable = load(senderFp); - append(new AMD64HotSpotEnterUnpackFramesStackFrameOp(threadRegister, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset(), framePcVariable, - senderSpVariable, senderFpVariable, saveRegisterOp)); - } - - @Override - public void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) { - Register threadRegister = getProviders().getRegisters().getThreadRegister(); - append(new AMD64HotSpotLeaveUnpackFramesStackFrameOp(threadRegister, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadLastJavaFpOffset(), saveRegisterOp)); - } - /** * @param savedRegisters the registers saved by this operation which may be subject to pruning * @param savedRegisterLocations the slots to which the registers are saved @@ -359,13 +328,6 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp return emitSaveRegisters(savedRegisters, savedRegisterLocations, supportsRemove); } - @Override - public SaveRegistersOp emitSaveAllRegisters() { - // We are saving all registers. - // TODO Save upper half of YMM registers. - return emitSaveAllRegisters(target().arch.getAvailableValueRegisters().toArray(), false); - } - protected void emitRestoreRegisters(AMD64SaveRegistersOp save) { append(new AMD64RestoreRegistersOp(save.getSlots().clone(), save)); } @@ -421,8 +383,12 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp if (stub != null) { if (stub.preservesRegisters()) { HotSpotLIRGenerationResult generationResult = getResult(); - assert !generationResult.getCalleeSaveInfo().containsKey(currentRuntimeCallInfo); - generationResult.getCalleeSaveInfo().put(currentRuntimeCallInfo, save); + LIRFrameState key = currentRuntimeCallInfo; + if (key == null) { + key = LIRFrameState.NO_STATE; + } + assert !generationResult.getCalleeSaveInfo().containsKey(key); + generationResult.getCalleeSaveInfo().put(key, save); emitRestoreRegisters(save); } } @@ -434,8 +400,7 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp @Override public Value emitLoadObjectAddress(Constant constant) { HotSpotObjectConstant objectConstant = (HotSpotObjectConstant) constant; - HotSpotLIRKindTool kindTool = (HotSpotLIRKindTool) getLIRKindTool(); - LIRKind kind = objectConstant.isCompressed() ? kindTool.getNarrowOopKind() : kindTool.getObjectKind(); + LIRKind kind = objectConstant.isCompressed() ? getLIRKindTool().getNarrowOopKind() : getLIRKindTool().getObjectKind(); Variable result = newVariable(kind); append(new AMD64HotSpotLoadAddressOp(result, constant, HotSpotConstantLoadAction.RESOLVE)); return result; @@ -444,8 +409,7 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp @Override public Value emitLoadMetaspaceAddress(Constant constant, HotSpotConstantLoadAction action) { HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) constant; - HotSpotLIRKindTool kindTool = (HotSpotLIRKindTool) getLIRKindTool(); - LIRKind kind = metaspaceConstant.isCompressed() ? kindTool.getNarrowPointerKind() : kindTool.getWordKind(); + LIRKind kind = metaspaceConstant.isCompressed() ? getLIRKindTool().getNarrowPointerKind() : getLIRKindTool().getWordKind(); Variable result = newVariable(kind); append(new AMD64HotSpotLoadAddressOp(result, constant, action)); return result; @@ -510,38 +474,6 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp return emitMove(timestamp.getLowResult()); } - @Override - public Value emitUncommonTrapCall(Value trapRequest, Value mode, SaveRegistersOp saveRegisterOp) { - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP); - - Register thread = getProviders().getRegisters().getThreadRegister(); - append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread)); - Variable result = super.emitForeignCall(linkage, null, thread.asValue(LIRKind.value(AMD64Kind.QWORD)), trapRequest, mode); - append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), config.threadLastJavaPcOffset(), thread)); - - Map calleeSaveInfo = getResult().getCalleeSaveInfo(); - assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); - calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); - - return result; - } - - @Override - public Value emitDeoptimizationFetchUnrollInfoCall(Value mode, SaveRegistersOp saveRegisterOp) { - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(FETCH_UNROLL_INFO); - - Register thread = getProviders().getRegisters().getThreadRegister(); - append(new AMD64HotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), thread)); - Variable result = super.emitForeignCall(linkage, null, thread.asValue(LIRKind.value(AMD64Kind.QWORD)), mode); - append(new AMD64HotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaFpOffset(), config.threadLastJavaPcOffset(), thread)); - - Map calleeSaveInfo = getResult().getCalleeSaveInfo(); - assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); - calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); - - return result; - } - @Override public void emitTailcall(Value[] args, Value address) { append(new AMD64TailcallOp(args, address)); @@ -621,21 +553,12 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp LIRInstruction op = getOrInitRescueSlotOp(); // insert dummy instruction into the start block LIR lir = getResult().getLIR(); - List instructions = lir.getLIRforBlock(lir.getControlFlowGraph().getStartBlock()); + ArrayList instructions = lir.getLIRforBlock(lir.getControlFlowGraph().getStartBlock()); instructions.add(1, op); - Debug.dump(Debug.INFO_LOG_LEVEL, lir, "created rescue dummy op"); + lir.getDebug().dump(DebugContext.INFO_LEVEL, lir, "created rescue dummy op"); } } - @Override - public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { - Variable frameSizeVariable = load(frameSize); - Variable framePcVariable = load(framePc); - Variable senderSpVariable = load(senderSp); - Variable initialInfoVariable = load(initialInfo); - append(new AMD64HotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable, config)); - } - @Override public Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull) { LIRKind inputKind = pointer.getValueKind(LIRKind.class); @@ -649,14 +572,15 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp // metaspace pointer Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0 || GeneratePIC.getValue()) { - if (GeneratePIC.getValue()) { + OptionValues options = getResult().getLIR().getOptions(); + if (encoding.hasBase() || GeneratePIC.getValue(options)) { + if (GeneratePIC.getValue(options)) { Variable baseAddress = newVariable(LIRKind.value(AMD64Kind.QWORD)); AMD64HotSpotMove.BaseMove move = new AMD64HotSpotMove.BaseMove(baseAddress, config); append(move); base = baseAddress; } else { - base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.base)); + base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); } } append(new AMD64HotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); @@ -677,14 +601,15 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp // metaspace pointer Variable result = newVariable(LIRKind.value(AMD64Kind.QWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0 || GeneratePIC.getValue()) { - if (GeneratePIC.getValue()) { + OptionValues options = getResult().getLIR().getOptions(); + if (encoding.hasBase() || GeneratePIC.getValue(options)) { + if (GeneratePIC.getValue(options)) { Variable baseAddress = newVariable(LIRKind.value(AMD64Kind.QWORD)); AMD64HotSpotMove.BaseMove move = new AMD64HotSpotMove.BaseMove(baseAddress, config); append(move); base = baseAddress; } else { - base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.base)); + base = emitLoadConstant(LIRKind.value(AMD64Kind.QWORD), JavaConstant.forLong(encoding.getBase())); } } append(new AMD64HotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); @@ -697,9 +622,10 @@ public class AMD64HotSpotLIRGenerator extends AMD64LIRGenerator implements HotSp if (address.getValueKind().getPlatformKind() == AMD64Kind.DWORD) { CompressEncoding encoding = config.getOopEncoding(); Value uncompressed; - if (encoding.shift <= 3) { + if (encoding.getShift() <= 3) { LIRKind wordKind = LIRKind.unknownReference(target().arch.getWordKind()); - uncompressed = new AMD64AddressValue(wordKind, getProviders().getRegisters().getHeapBaseRegister().asValue(wordKind), asAllocatable(address), Scale.fromInt(1 << encoding.shift), 0); + uncompressed = new AMD64AddressValue(wordKind, getProviders().getRegisters().getHeapBaseRegister().asValue(wordKind), asAllocatable(address), Scale.fromInt(1 << encoding.getShift()), + 0); } else { uncompressed = emitUncompress(address, encoding, false); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java deleted file mode 100644 index 40155af38f3..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.amd64; - -import org.graalvm.compiler.asm.amd64.AMD64Address; -import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.Opcode; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.framemap.FrameMap; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.RegisterSaveLayout; -import jdk.vm.ci.meta.JavaKind; - -/** - * Emits code that leaves a stack frame which is tailored to call the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME") -final class AMD64HotSpotLeaveUnpackFramesStackFrameOp extends AMD64LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64HotSpotLeaveUnpackFramesStackFrameOp.class); - - private final Register threadRegister; - private final int threadLastJavaSpOffset; - private final int threadLastJavaPcOffset; - private final int threadLastJavaFpOffset; - - private final SaveRegistersOp saveRegisterOp; - - AMD64HotSpotLeaveUnpackFramesStackFrameOp(Register threadRegister, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadLastJavaFpOffset, SaveRegistersOp saveRegisterOp) { - super(TYPE); - this.threadRegister = threadRegister; - this.threadLastJavaSpOffset = threadLastJavaSpOffset; - this.threadLastJavaPcOffset = threadLastJavaPcOffset; - this.threadLastJavaFpOffset = threadLastJavaFpOffset; - this.saveRegisterOp = saveRegisterOp; - } - - @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - FrameMap frameMap = crb.frameMap; - RegisterConfig registerConfig = frameMap.getRegisterConfig(); - RegisterSaveLayout registerSaveLayout = saveRegisterOp.getMap(frameMap); - Register stackPointerRegister = registerConfig.getFrameRegister(); - - // Restore stack pointer. - masm.movq(stackPointerRegister, new AMD64Address(threadRegister, threadLastJavaSpOffset)); - - // Clear last Java frame values. - masm.movslq(new AMD64Address(threadRegister, threadLastJavaSpOffset), 0); - masm.movslq(new AMD64Address(threadRegister, threadLastJavaPcOffset), 0); - masm.movslq(new AMD64Address(threadRegister, threadLastJavaFpOffset), 0); - - // Restore return values. - final int stackSlotSize = frameMap.getTarget().wordSize; - Register integerResultRegister = registerConfig.getReturnRegister(JavaKind.Long); - masm.movptr(integerResultRegister, new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(integerResultRegister) * stackSlotSize)); - - Register floatResultRegister = registerConfig.getReturnRegister(JavaKind.Double); - masm.movdbl(floatResultRegister, new AMD64Address(stackPointerRegister, registerSaveLayout.registerToSlot(floatResultRegister) * stackSlotSize)); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java index 24b11237bda..ae36c40fbdc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoadConfigValueOp.java @@ -51,7 +51,7 @@ public final class AMD64HotSpotLoadConfigValueOp extends AMD64LIRInstruction { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { AMD64Kind kind = (AMD64Kind) result.getPlatformKind(); Register reg = asRegister(result); AMD64Address placeholder = masm.getPlaceholder(-1); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java index 36292b06fc3..3b11a891691 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java @@ -27,12 +27,13 @@ import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvide import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_EXP_STUB; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG10_STUB; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_LOG_STUB; -import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_SIN_STUB; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_POW_STUB; +import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_SIN_STUB; import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotForeignCallsProvider.ARITHMETIC_TAN_STUB; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; @@ -43,6 +44,7 @@ import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; import org.graalvm.compiler.hotspot.replacements.profiling.ProbabilisticProfileSnippets; import org.graalvm.compiler.nodes.calc.FloatConvertNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.amd64.AMD64ConvertSnippets; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation; @@ -62,10 +64,11 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider } @Override - public void initialize(HotSpotProviders providers, GraalHotSpotVMConfig config) { - convertSnippets = new AMD64ConvertSnippets.Templates(providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue() ? new ProbabilisticProfileSnippets.Templates(providers, providers.getCodeCache().getTarget()) : null; - super.initialize(providers, config); + public void initialize(OptionValues options, Iterable factories, HotSpotProviders providers, GraalHotSpotVMConfig config) { + convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); + profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) + ? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget()) : null; + super.initialize(options, factories, providers, config); } @Override @@ -81,7 +84,7 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider @Override protected ForeignCallDescriptor toForeignCall(UnaryOperation operation) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(runtime.getOptions())) { switch (operation) { case LOG: return ARITHMETIC_LOG_STUB; @@ -105,7 +108,7 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider @Override protected ForeignCallDescriptor toForeignCall(BinaryOperation operation) { - if (GraalArithmeticStubs.getValue()) { + if (GraalArithmeticStubs.getValue(runtime.getOptions())) { switch (operation) { case POW: return ARITHMETIC_POW_STUB; @@ -118,7 +121,7 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider } @Override - public boolean supportSubwordCompare(int bits) { - return true; + public Integer smallestCompareWidth() { + return 8; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java index 168282ebcbf..a5c75f5958b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMove.java @@ -34,9 +34,9 @@ import static jdk.vm.ci.code.ValueUtil.isStackSlot; import org.graalvm.compiler.asm.Label; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; @@ -67,7 +67,7 @@ public class AMD64HotSpotMove { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { throw GraalError.shouldNotReachHere("Object constant load should not be happening directly"); } boolean compressed = input.isCompressed(); @@ -146,7 +146,7 @@ public class AMD64HotSpotMove { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { throw GraalError.shouldNotReachHere("Metaspace constant load should not be happening directly"); } boolean compressed = input.isCompressed(); @@ -204,7 +204,7 @@ public class AMD64HotSpotMove { AMD64Move.move(AMD64Kind.QWORD, crb, masm, result, input); Register resReg = asRegister(result); - if (encoding.base != 0 || GeneratePIC.getValue()) { + if (encoding.hasBase() || GeneratePIC.getValue(crb.getOptions())) { Register baseReg = asRegister(baseRegister); if (!nonNull) { masm.testq(resReg, resReg); @@ -213,8 +213,8 @@ public class AMD64HotSpotMove { masm.subq(resReg, baseReg); } - if (encoding.shift != 0) { - masm.shrq(resReg, encoding.shift); + if (encoding.hasShift()) { + masm.shrq(resReg, encoding.getShift()); } } } @@ -243,15 +243,15 @@ public class AMD64HotSpotMove { AMD64Move.move(AMD64Kind.DWORD, crb, masm, result, input); Register resReg = asRegister(result); - if (encoding.shift != 0) { - masm.shlq(resReg, encoding.shift); + if (encoding.getShift() != 0) { + masm.shlq(resReg, encoding.getShift()); } - if (encoding.base != 0 || GeneratePIC.getValue()) { + if (encoding.hasBase() || GeneratePIC.getValue(crb.getOptions())) { if (nonNull) { masm.addq(resReg, asRegister(baseRegister)); } else { - if (encoding.shift == 0) { + if (!encoding.hasShift()) { // if encoding.shift != 0, the flags are already set by the shlq masm.testq(resReg, resReg); } @@ -268,17 +268,17 @@ public class AMD64HotSpotMove { public static void decodeKlassPointer(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register register, Register scratch, AMD64Address address, GraalHotSpotVMConfig config) { CompressEncoding encoding = config.getKlassEncoding(); masm.movl(register, address); - if (encoding.shift != 0) { - assert encoding.alignment == encoding.shift : "Decode algorithm is wrong"; - masm.shlq(register, encoding.alignment); + if (encoding.getShift() != 0) { + masm.shlq(register, encoding.getShift()); } - if (GeneratePIC.getValue() || encoding.base != 0) { - if (GeneratePIC.getValue()) { + boolean pic = GeneratePIC.getValue(crb.getOptions()); + if (pic || encoding.hasBase()) { + if (pic) { masm.movq(scratch, masm.getPlaceholder(-1)); crb.recordMark(config.MARKID_NARROW_KLASS_BASE_ADDRESS); } else { - assert encoding.base != 0; - masm.movq(scratch, encoding.base); + assert encoding.getBase() != 0; + masm.movq(scratch, encoding.getBase()); } masm.addq(register, scratch); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java index 893a35263f8..ff8fa82f53b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java @@ -23,6 +23,7 @@ package org.graalvm.compiler.hotspot.amd64; import org.graalvm.compiler.core.amd64.AMD64MoveFactory; +import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction; import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; @@ -40,11 +41,13 @@ public class AMD64HotSpotMoveFactory extends AMD64MoveFactory { } @Override - public boolean canInlineConstant(JavaConstant c) { + public boolean canInlineConstant(Constant c) { if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { return true; } else if (c instanceof HotSpotObjectConstant) { return ((HotSpotObjectConstant) c).isCompressed(); + } else if (c instanceof HotSpotMetaspaceConstant) { + return ((HotSpotMetaspaceConstant) c).isCompressed(); } else { return super.canInlineConstant(c); } @@ -55,7 +58,7 @@ public class AMD64HotSpotMoveFactory extends AMD64MoveFactory { if (value instanceof HotSpotConstant) { return ((HotSpotConstant) value).isCompressed(); } - return true; + return super.allowConstantToStackMove(value); } @Override @@ -70,4 +73,19 @@ public class AMD64HotSpotMoveFactory extends AMD64MoveFactory { return super.createLoad(dst, src); } } + + @Override + public LIRInstruction createStackLoad(AllocatableValue dst, Constant src) { + if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(src)) { + return super.createStackLoad(dst, JavaConstant.INT_0); + } else if (src instanceof HotSpotObjectConstant) { + assert ((HotSpotConstant) src).isCompressed(); + return new AMD64HotSpotMove.HotSpotLoadObjectConstantOp(dst, (HotSpotObjectConstant) src); + } else if (src instanceof HotSpotMetaspaceConstant) { + assert ((HotSpotConstant) src).isCompressed(); + return new AMD64HotSpotMove.HotSpotLoadMetaspaceConstantOp(dst, (HotSpotMetaspaceConstant) src); + } else { + return super.createStackLoad(dst, src); + } + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeCostProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeCostProvider.java deleted file mode 100644 index 24e7d674b37..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeCostProvider.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.amd64; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_15; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_50; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_6; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_80; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_30; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4; - -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.hotspot.nodes.HotSpotNodeCostProvider; -import org.graalvm.compiler.nodeinfo.NodeCycles; -import org.graalvm.compiler.nodeinfo.NodeSize; -import org.graalvm.compiler.nodes.ReturnNode; -import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode; -import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; - -import jdk.vm.ci.amd64.AMD64; -import jdk.vm.ci.amd64.AMD64.CPUFeature; -import jdk.vm.ci.code.TargetDescription; - -public class AMD64HotSpotNodeCostProvider extends HotSpotNodeCostProvider { - private final boolean avx2; - private final boolean sse41; - - public AMD64HotSpotNodeCostProvider(TargetDescription target) { - this.avx2 = ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX2); - this.sse41 = ((AMD64) target.arch).getFeatures().contains(CPUFeature.SSE4_1); - } - - @Override - public NodeCycles cycles(Node n) { - if (n instanceof UnaryMathIntrinsicNode) { - UnaryMathIntrinsicNode u = (UnaryMathIntrinsicNode) n; - switch (u.getOperation()) { - case LOG: - case LOG10: - return CYCLES_15; - default: - break; - } - } else if (n instanceof ReturnNode) { - return CYCLES_6; - } else if (n instanceof ArrayEqualsNode) { - if (avx2) { - return CYCLES_50; - } else if (sse41) { - return CYCLES_80; - } - } - return super.cycles(n); - } - - @Override - public NodeSize size(Node n) { - if (n instanceof UnaryMathIntrinsicNode) { - UnaryMathIntrinsicNode u = (UnaryMathIntrinsicNode) n; - switch (u.getOperation()) { - case LOG: - case LOG10: - return SIZE_30; - default: - break; - } - } else if (n instanceof ReturnNode) { - return SIZE_4; - } - return super.size(n); - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java index 09a6d98ba9c..a81cb6d222e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java @@ -22,27 +22,24 @@ */ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; import static jdk.vm.ci.amd64.AMD64.rbp; import static jdk.vm.ci.code.ValueUtil.isStackSlot; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; import org.graalvm.compiler.core.amd64.AMD64NodeLIRBuilder; import org.graalvm.compiler.core.amd64.AMD64NodeMatchRules; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.gen.DebugInfoBuilder; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.amd64.AMD64BreakpointOp; -import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.nodes.BreakpointNode; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; @@ -179,25 +176,12 @@ public class AMD64HotSpotNodeLIRBuilder extends AMD64NodeLIRBuilder implements H @Override public void visitFullInfopointNode(FullInfopointNode i) { if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { - Debug.log("Ignoring InfopointNode for AFTER_BCI"); + i.getDebug().log("Ignoring InfopointNode for AFTER_BCI"); } else { super.visitFullInfopointNode(i); } } - @Override - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - Value expected = gen.loadNonConst(operand(x.expectedValue())); - Variable newVal = gen.load(operand(x.newValue())); - assert expected.getValueKind().equals(newVal.getValueKind()); - - RegisterValue raxLocal = AMD64.rax.asValue(expected.getValueKind()); - gen.emitMove(raxLocal, expected); - append(new CompareAndSwapOp((AMD64Kind) expected.getPlatformKind(), raxLocal, getGen().asAddressValue(operand(x.getAddress())), raxLocal, newVal)); - - setResult(x, gen.emitMove(raxLocal)); - } - @Override public void visitBreakpointNode(BreakpointNode node) { JavaType[] sig = new JavaType[node.arguments().size()]; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java index fd08e39b489..ce49590322e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java @@ -81,8 +81,8 @@ class AMD64HotSpotRegisterAllocationConfig extends RegisterAllocationConfig { }; // @formatter:on - AMD64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig) { - super(registerConfig); + AMD64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { + super(registerConfig, allocationRestrictedTo); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java index 10321188ab0..7a5ee813a89 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSafepointOp.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.asm.NumUtil.isInt; +import static org.graalvm.compiler.core.common.NumUtil.isInt; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static jdk.vm.ci.amd64.AMD64.rax; @@ -63,7 +63,7 @@ public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction { super(TYPE); this.state = state; this.config = config; - if (isPollingPageFar(config) || ImmutableCode.getValue()) { + if (isPollingPageFar(config) || ImmutableCode.getValue(tool.getOptions())) { temp = tool.getLIRGeneratorTool().newVariable(LIRKind.value(tool.getLIRGeneratorTool().target().arch.getWordKind())); } else { // Don't waste a register if it's unneeded @@ -87,13 +87,13 @@ public final class AMD64HotSpotSafepointOp extends AMD64LIRInstruction { public static void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler asm, GraalHotSpotVMConfig config, boolean atReturn, LIRFrameState state, Register scratch) { assert !atReturn || state == null : "state is unneeded at return"; - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(crb.getOptions())) { JavaKind hostWordKind = JavaKind.Long; int alignment = hostWordKind.getBitCount() / Byte.SIZE; JavaConstant pollingPageAddress = JavaConstant.forIntegerKind(hostWordKind, config.safepointPollingAddress); // This move will be patched to load the safepoint page from a data segment // co-located with the immutable code. - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(crb.getOptions())) { asm.movq(scratch, asm.getPlaceholder(-1)); } else { asm.movq(scratch, (AMD64Address) crb.recordDataReferenceInCode(pollingPageAddress, alignment)); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesCreator.java similarity index 75% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesProvider.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesCreator.java index 431d90ca4b9..fa9ea20cf5f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesCreator.java @@ -22,23 +22,24 @@ */ package org.graalvm.compiler.hotspot.amd64; -import org.graalvm.compiler.core.amd64.AMD64SuitesProvider; -import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.core.amd64.AMD64SuitesCreator; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.hotspot.lir.HotSpotZapRegistersPhase; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; -public class AMD64HotSpotSuitesProvider extends AMD64SuitesProvider { +public class AMD64HotSpotSuitesCreator extends AMD64SuitesCreator { - public AMD64HotSpotSuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) { + public AMD64HotSpotSuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) { super(compilerConfiguration, plugins); } @Override - public LIRSuites createLIRSuites() { - LIRSuites lirSuites = super.createLIRSuites(); - if (GraalOptions.DetailedAsserts.getValue()) { + public LIRSuites createLIRSuites(OptionValues options) { + LIRSuites lirSuites = super.createLIRSuites(options); + if (Assertions.detailedAssertionsEnabled(options)) { lirSuites.getPostAllocationOptimizationStage().appendPhase(new HotSpotZapRegistersPhase()); } return lirSuites; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java index 15956d35052..39507dd2b63 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64MathStub.java @@ -35,6 +35,7 @@ import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.stubs.SnippetStub; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode; import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation; import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode; @@ -45,8 +46,8 @@ import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOpera */ public class AMD64MathStub extends SnippetStub { - public AMD64MathStub(ForeignCallDescriptor descriptor, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super(snippetName(descriptor), providers, linkage); + public AMD64MathStub(ForeignCallDescriptor descriptor, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super(snippetName(descriptor), options, providers, linkage); } private static String snippetName(ForeignCallDescriptor descriptor) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64RawNativeCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64RawNativeCallNode.java index 2391ec6dd9c..4d51f5c734c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64RawNativeCallNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64RawNativeCallNode.java @@ -23,7 +23,6 @@ package org.graalvm.compiler.hotspot.amd64; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; import org.graalvm.compiler.core.amd64.AMD64NodeLIRBuilder; import org.graalvm.compiler.core.common.type.RawPointerStamp; @@ -32,6 +31,7 @@ import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; @@ -46,7 +46,7 @@ import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.Value; -@NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "Native call is a block hole", size = SIZE_20) +@NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "Native call is a block hole", size = NodeSize.SIZE_UNKNOWN) public final class AMD64RawNativeCallNode extends FixedWithNextNode implements LIRLowerable { public static final NodeClass TYPE = NodeClass.create(AMD64RawNativeCallNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64UncommonTrapStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64UncommonTrapStub.java deleted file mode 100644 index a4ca9d352e4..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64UncommonTrapStub.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.amd64; - -import static jdk.vm.ci.amd64.AMD64.r10; -import static jdk.vm.ci.amd64.AMD64.r11; -import static jdk.vm.ci.amd64.AMD64.r13; -import static jdk.vm.ci.amd64.AMD64.r14; -import static jdk.vm.ci.amd64.AMD64.r8; -import static jdk.vm.ci.amd64.AMD64.r9; -import static jdk.vm.ci.amd64.AMD64.rbx; -import static jdk.vm.ci.amd64.AMD64.rcx; -import static jdk.vm.ci.amd64.AMD64.rdi; -import static jdk.vm.ci.amd64.AMD64.rdx; -import static jdk.vm.ci.amd64.AMD64.rsi; - -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.UncommonTrapStub; - -import jdk.vm.ci.code.RegisterArray; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.amd64.AMD64HotSpotRegisterConfig; - -final class AMD64UncommonTrapStub extends UncommonTrapStub { - - private RegisterConfig registerConfig; - - AMD64UncommonTrapStub(HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); - RegisterArray allocatable = new RegisterArray(rbx, rcx, rdx, rsi, rdi, r8, r9, r10, r11, r13, r14); - registerConfig = new AMD64HotSpotRegisterConfig(target, allocatable, config.windowsOs); - } - - @Override - public RegisterConfig getRegisterConfig() { - return registerConfig; - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCDeoptimizationStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCDeoptimizationStub.java deleted file mode 100644 index eb8e69b27fc..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCDeoptimizationStub.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.sparc; - -import static jdk.vm.ci.sparc.SPARC.g1; -import static jdk.vm.ci.sparc.SPARC.g3; -import static jdk.vm.ci.sparc.SPARC.g4; -import static jdk.vm.ci.sparc.SPARC.g5; -import static jdk.vm.ci.sparc.SPARC.o0; -import static jdk.vm.ci.sparc.SPARC.o1; -import static jdk.vm.ci.sparc.SPARC.o2; -import static jdk.vm.ci.sparc.SPARC.o3; -import static jdk.vm.ci.sparc.SPARC.o4; - -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.DeoptimizationStub; - -import jdk.vm.ci.code.RegisterArray; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.sparc.SPARCHotSpotRegisterConfig; - -final class SPARCDeoptimizationStub extends DeoptimizationStub { - - private RegisterConfig registerConfig; - - SPARCDeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); - // This is basically the maximum we can spare. All other G and O register are used. - RegisterArray allocatable = new RegisterArray(g1, g3, g4, g5, o0, o1, o2, o3, o4); - registerConfig = new SPARCHotSpotRegisterConfig(target, allocatable); - } - - @Override - public RegisterConfig getRegisterConfig() { - return registerConfig; - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java index abe2d0ba2d7..7c1392f2c6d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java @@ -22,13 +22,6 @@ */ package org.graalvm.compiler.hotspot.sparc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.isGlobalRegister; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_NOT_TAKEN; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CC.Xcc; -import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual; -import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.sparc.SPARC.g0; @@ -40,10 +33,16 @@ import static jdk.vm.ci.sparc.SPARC.l7; import static jdk.vm.ci.sparc.SPARC.o0; import static jdk.vm.ci.sparc.SPARC.o7; import static jdk.vm.ci.sparc.SPARC.sp; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.isGlobalRegister; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_NOT_TAKEN; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CC.Xcc; +import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual; +import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry; +import java.util.ArrayList; import java.util.HashSet; -import java.util.List; -import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -60,13 +59,13 @@ import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotDataBuilder; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotHostBackend; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -92,6 +91,10 @@ import org.graalvm.compiler.lir.sparc.SPARCLIRInstructionMixin.SizeEstimate; import org.graalvm.compiler.lir.sparc.SPARCTailDelayedLIRInstruction; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.EconomicSet; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.Register; @@ -114,7 +117,7 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { } private static class SizeEstimateStatistics { - private static final ConcurrentHashMap counters = new ConcurrentHashMap<>(); + private static final ConcurrentHashMap counters = new ConcurrentHashMap<>(); private final String suffix; SizeEstimateStatistics(String suffix) { @@ -122,10 +125,10 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { this.suffix = suffix; } - public void add(Class c, int count) { + public void add(Class c, int count, DebugContext debug) { String name = SizeEstimateStatistics.class.getSimpleName() + "_" + c.getSimpleName() + "." + suffix; - DebugCounter m = counters.computeIfAbsent(name, (n) -> Debug.counter(n)); - m.add(count); + CounterKey m = counters.computeIfAbsent(name, (n) -> DebugContext.counter(n)); + m.add(debug, count); } } @@ -203,7 +206,7 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { } } - if (ZapStackOnMethodEntry.getValue()) { + if (ZapStackOnMethodEntry.getValue(crb.getOptions())) { final int slotSize = 8; for (int i = 0; i < frameSize / slotSize; ++i) { // 0xC1C1C1C1 @@ -235,7 +238,10 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { // On SPARC we always use stack frames. HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null); DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget()); - CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, dataBuilder, frameContext, compilationResult); + OptionValues options = lir.getOptions(); + DebugContext debug = lir.getDebug(); + CompilationResultBuilder crb = factory.createBuilder(getProviders().getCodeCache(), getProviders().getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, debug, + compilationResult); crb.setTotalFrameSize(frameMap.totalFrameSize()); crb.setMaxInterpreterFrameSize(gen.getMaxInterpreterFrameSize()); StackSlot deoptimizationRescueSlot = gen.getDeoptimizationRescueSlot(); @@ -245,11 +251,11 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { if (stub != null) { // Even on sparc we need to save floating point registers - Set destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); - Map calleeSaveInfo = gen.getCalleeSaveInfo(); + EconomicSet destroyedCallerRegisters = gatherDestroyedCallerRegisters(lir); + EconomicMap calleeSaveInfo = gen.getCalleeSaveInfo(); updateStub(stub, destroyedCallerRegisters, calleeSaveInfo, frameMap); } - assert registerSizePredictionValidator(crb); + assert registerSizePredictionValidator(crb, debug); return crb; } @@ -257,14 +263,19 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { * Registers a verifier which checks if the LIRInstructions estimate of constants size is * greater or equal to the actual one. */ - private static boolean registerSizePredictionValidator(final CompilationResultBuilder crb) { + private static boolean registerSizePredictionValidator(final CompilationResultBuilder crb, DebugContext debug) { /** * Used to hold state between beforeOp and afterOp */ class ValidationState { LIRInstruction op; + final DebugContext debug; int constantSizeBefore; + ValidationState(DebugContext debug) { + this.debug = debug; + } + public void before(LIRInstruction before) { assert op == null : "LIRInstruction " + op + " no after call received"; op = before; @@ -279,8 +290,8 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { org.graalvm.compiler.lir.sparc.SPARCLIRInstructionMixin.SizeEstimate size = ((SPARCLIRInstructionMixin) op).estimateSize(); assert size != null : "No size prediction available for op: " + op; Class c = op.getClass(); - CONSTANT_ESTIMATED_STATS.add(c, size.constantSize); - CONSTANT_ACTUAL_STATS.add(c, actual); + CONSTANT_ESTIMATED_STATS.add(c, size.constantSize, debug); + CONSTANT_ACTUAL_STATS.add(c, actual, debug); assert size.constantSize >= actual : "Op " + op + " exceeded estimated constant size; predicted: " + size.constantSize + " actual: " + actual; } else { assert actual == 0 : "Op " + op + " emitted to DataSection without any estimate."; @@ -289,7 +300,7 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { constantSizeBefore = 0; } } - final ValidationState state = new ValidationState(); + final ValidationState state = new ValidationState(debug); crb.setOpCallback(op -> state.before(op), op -> state.after(op)); return true; } @@ -421,7 +432,7 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { * possible. */ private static void stuffDelayedControlTransfers(LIR l, AbstractBlockBase block) { - List instructions = l.getLIRforBlock(block); + ArrayList instructions = l.getLIRforBlock(block); if (instructions.size() >= 2) { LIRDependencyAccumulator acc = new LIRDependencyAccumulator(); SPARCDelayedControlTransfer delayedTransfer = null; @@ -497,14 +508,14 @@ public class SPARCHotSpotBackend extends HotSpotHostBackend { } @Override - public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig) { + public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; - return new SPARCHotSpotRegisterAllocationConfig(registerConfigNonNull); + return new SPARCHotSpotRegisterAllocationConfig(registerConfigNonNull, allocationRestrictedTo); } @Override - public Set translateToCallerRegisters(Set calleeRegisters) { - HashSet callerRegisters = new HashSet<>(calleeRegisters.size()); + public EconomicSet translateToCallerRegisters(EconomicSet calleeRegisters) { + EconomicSet callerRegisters = EconomicSet.create(Equivalence.IDENTITY, calleeRegisters.size()); for (Register register : calleeRegisters) { if (l0.number <= register.number && register.number <= l7.number) { // do nothing diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java index 821348a75c3..eadc3cca4e8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java @@ -27,12 +27,13 @@ import java.util.Set; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.core.sparc.SPARCAddressLowering; -import org.graalvm.compiler.core.sparc.SPARCSuitesProvider; +import org.graalvm.compiler.core.sparc.SPARCSuitesCreator; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotBackendFactory; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotReplacementsImpl; +import org.graalvm.compiler.hotspot.meta.AddressLoweringHotSpotSuitesProvider; import org.graalvm.compiler.hotspot.meta.HotSpotConstantFieldProvider; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider; @@ -44,11 +45,9 @@ import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSnippetReflectionProvider; import org.graalvm.compiler.hotspot.meta.HotSpotStampProvider; import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider; -import org.graalvm.compiler.hotspot.nodes.HotSpotNodeCostProvider; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.spi.LoweringProvider; -import org.graalvm.compiler.nodes.spi.NodeCostProvider; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.util.Providers; @@ -98,26 +97,25 @@ public class SPARCHotSpotBackendFactory implements HotSpotBackendFactory { HotSpotForeignCallsProvider foreignCalls = new SPARCHotSpotForeignCallsProvider(jvmciRuntime, runtime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters); LoweringProvider lowerer = createLowerer(runtime, metaAccess, foreignCalls, registers, constantReflection, target); HotSpotStampProvider stampProvider = new HotSpotStampProvider(); - NodeCostProvider nodeCostProvider = new SPARCHotSpotNodeCostProvider(); - Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, nodeCostProvider); + Providers p = new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider); HotSpotSnippetReflectionProvider snippetReflection = new HotSpotSnippetReflectionProvider(runtime, constantReflection, wordTypes); BytecodeProvider bytecodeProvider = new ClassfileBytecodeProvider(metaAccess, snippetReflection); - HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(p, snippetReflection, bytecodeProvider, target); - Plugins plugins = createGraphBuilderPlugins(config, metaAccess, constantReflection, foreignCalls, stampProvider, snippetReflection, replacements, wordTypes); + HotSpotReplacementsImpl replacements = new HotSpotReplacementsImpl(runtime.getOptions(), p, snippetReflection, bytecodeProvider, target); + Plugins plugins = createGraphBuilderPlugins(compilerConfiguration, config, metaAccess, constantReflection, foreignCalls, stampProvider, snippetReflection, replacements, wordTypes); replacements.setGraphBuilderPlugins(plugins); HotSpotSuitesProvider suites = createSuites(config, runtime, compilerConfiguration, plugins, replacements); - HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, nodeCostProvider, suites, registers, + HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers, snippetReflection, wordTypes, plugins); return createBackend(config, runtime, providers); } - protected Plugins createGraphBuilderPlugins(GraalHotSpotVMConfig config, HotSpotMetaAccessProvider metaAccess, HotSpotConstantReflectionProvider constantReflection, - HotSpotForeignCallsProvider foreignCalls, HotSpotStampProvider stampProvider, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, - HotSpotWordTypes wordTypes) { - Plugins plugins = HotSpotGraphBuilderPlugins.create(config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); - SPARCGraphBuilderPlugins.register(plugins, replacements.getReplacementBytecodeProvider()); + protected Plugins createGraphBuilderPlugins(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotMetaAccessProvider metaAccess, + HotSpotConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls, HotSpotStampProvider stampProvider, + HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) { + Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, stampProvider, replacements); + SPARCGraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider()); return plugins; } @@ -126,7 +124,7 @@ public class SPARCHotSpotBackendFactory implements HotSpotBackendFactory { */ protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins, Replacements replacements) { - return new HotSpotSuitesProvider(new SPARCSuitesProvider(compilerConfiguration, plugins), config, runtime, new SPARCAddressLowering()); + return new AddressLoweringHotSpotSuitesProvider(new SPARCSuitesCreator(compilerConfiguration, plugins), config, runtime, new SPARCAddressLowering()); } protected SPARCHotSpotBackend createBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) { @@ -142,10 +140,6 @@ public class SPARCHotSpotBackendFactory implements HotSpotBackendFactory { return new HotSpotRegisters(SPARC.g2, SPARC.g6, SPARC.sp); } - protected HotSpotNodeCostProvider createNodeCostProvider() { - return new SPARCHotSpotNodeCostProvider(); - } - @SuppressWarnings("unused") private static Value[] createNativeABICallerSaveRegisters(GraalHotSpotVMConfig config, RegisterConfig regConfig) { Set callerSavedRegisters = new HashSet<>(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java deleted file mode 100644 index 418ea884fbe..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.sparc; - -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARC.STACK_BIAS; -import static jdk.vm.ci.sparc.SPARC.g0; -import static jdk.vm.ci.sparc.SPARC.i0; -import static jdk.vm.ci.sparc.SPARC.i1; -import static jdk.vm.ci.sparc.SPARC.i2; -import static jdk.vm.ci.sparc.SPARC.i3; -import static jdk.vm.ci.sparc.SPARC.i4; -import static jdk.vm.ci.sparc.SPARC.l7; -import static jdk.vm.ci.sparc.SPARC.o0; -import static jdk.vm.ci.sparc.SPARC.o1; -import static jdk.vm.ci.sparc.SPARC.o2; -import static jdk.vm.ci.sparc.SPARC.o3; -import static jdk.vm.ci.sparc.SPARC.o4; -import static jdk.vm.ci.sparc.SPARC.o5; -import static jdk.vm.ci.sparc.SPARC.o7; -import static jdk.vm.ci.sparc.SPARC.sp; - -import org.graalvm.compiler.asm.sparc.SPARCAddress; -import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; -import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.Opcode; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.sparc.SPARCLIRInstruction; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.meta.AllocatableValue; -import jdk.vm.ci.meta.PlatformKind; - -/** - * Emits code that enters a stack frame which is tailored to call the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@Opcode("ENTER_UNPACK_FRAMES_STACK_FRAME") -final class SPARCHotSpotEnterUnpackFramesStackFrameOp extends SPARCLIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotEnterUnpackFramesStackFrameOp.class); - - private final Register thread; - private final int threadLastJavaSpOffset; - private final int threadLastJavaPcOffset; - @Alive(REG) AllocatableValue framePc; - @Alive(REG) AllocatableValue senderSp; - @Temp(REG) AllocatableValue scratch; - @Temp(REG) AllocatableValue callerReturnPc; - - SPARCHotSpotEnterUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, AllocatableValue framePc, AllocatableValue senderSp, AllocatableValue scratch, - PlatformKind wordKind) { - super(TYPE); - this.thread = thread; - this.threadLastJavaSpOffset = threadLastJavaSpOffset; - this.threadLastJavaPcOffset = threadLastJavaPcOffset; - this.framePc = framePc; - this.senderSp = senderSp; - this.scratch = scratch; - callerReturnPc = o7.asValue(LIRKind.value(wordKind)); - } - - @Override - public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - final int totalFrameSize = crb.frameMap.totalFrameSize(); - Register framePcRegister = asRegister(framePc); - Register senderSpRegister = asRegister(senderSp); - Register scratchRegister = asRegister(scratch); - - // Save final sender SP to O5_savedSP. - masm.mov(senderSpRegister, o5); - - // Load final frame PC. - masm.mov(framePcRegister, asRegister(callerReturnPc)); - - // Allocate a full sized frame. - masm.save(sp, -totalFrameSize, sp); - - masm.mov(i0, o0); - masm.mov(i1, o1); - masm.mov(i2, o2); - masm.mov(i3, o3); - masm.mov(i4, o4); - - // Set up last Java values. - masm.add(sp, STACK_BIAS, scratchRegister); - masm.stx(scratchRegister, new SPARCAddress(thread, threadLastJavaSpOffset)); - - // Clear last Java PC. - masm.stx(g0, new SPARCAddress(thread, threadLastJavaPcOffset)); - - /* - * Safe thread register manually since we are not using LEAF_SP for {@link - * DeoptimizationStub#UNPACK_FRAMES}. - */ - masm.mov(thread, l7); - } - - @Override - public boolean leavesRegisterWindow() { - return true; - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java index 58a9bbe75c9..795119fe9ab 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java @@ -22,30 +22,27 @@ */ package org.graalvm.compiler.hotspot.sparc; -import static org.graalvm.compiler.core.common.LocationIdentity.any; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; -import static org.graalvm.compiler.hotspot.HotSpotHostBackend.DEOPTIMIZATION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER; -import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static jdk.vm.ci.meta.Value.ILLEGAL; import static jdk.vm.ci.sparc.SPARC.i0; import static jdk.vm.ci.sparc.SPARC.i1; import static jdk.vm.ci.sparc.SPARC.o0; import static jdk.vm.ci.sparc.SPARC.o1; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.JUMP_ADDRESS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP; +import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32; +import static org.graalvm.word.LocationIdentity.any; import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.WordTypes; import jdk.vm.ci.code.CallingConvention; @@ -69,7 +66,7 @@ public class SPARCHotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro } @Override - public void initialize(HotSpotProviders providers) { + public void initialize(HotSpotProviders providers, OptionValues options) { GraalHotSpotVMConfig config = runtime.getVMConfig(); TargetDescription target = providers.getCodeCache().getTarget(); PlatformKind word = target.arch.getWordKind(); @@ -86,17 +83,12 @@ public class SPARCHotSpotForeignCallsProvider extends HotSpotHostForeignCallsPro register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER, 0L, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, any())); register(new HotSpotForeignCallLinkageImpl(EXCEPTION_HANDLER_IN_CALLER, JUMP_ADDRESS, PRESERVES_REGISTERS, LEAF_NOFP, outgoingExceptionCc, incomingExceptionCc, NOT_REEXECUTABLE, any())); - if (PreferGraalStubs.getValue()) { - link(new SPARCDeoptimizationStub(providers, target, registerStubCall(DEOPTIMIZATION_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); - link(new SPARCUncommonTrapStub(providers, target, registerStubCall(UNCOMMON_TRAP_HANDLER, REEXECUTABLE, LEAF, NO_LOCATIONS))); - } - if (config.useCRC32Intrinsics) { // This stub does callee saving registerForeignCall(UPDATE_BYTES_CRC32, config.updateBytesCRC32Stub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, NOT_REEXECUTABLE, any()); } - super.initialize(providers); + super.initialize(providers, options); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java index b6a2b520bc7..29a70ce9d17 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLIRGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -22,66 +22,27 @@ */ package org.graalvm.compiler.hotspot.sparc; -import static org.graalvm.compiler.hotspot.HotSpotBackend.FETCH_UNROLL_INFO; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNCOMMON_TRAP; -import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; -import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; -import static jdk.vm.ci.sparc.SPARC.d32; -import static jdk.vm.ci.sparc.SPARC.d34; -import static jdk.vm.ci.sparc.SPARC.d36; -import static jdk.vm.ci.sparc.SPARC.d38; -import static jdk.vm.ci.sparc.SPARC.d40; -import static jdk.vm.ci.sparc.SPARC.d42; -import static jdk.vm.ci.sparc.SPARC.d44; -import static jdk.vm.ci.sparc.SPARC.d46; -import static jdk.vm.ci.sparc.SPARC.d48; -import static jdk.vm.ci.sparc.SPARC.d50; -import static jdk.vm.ci.sparc.SPARC.d52; -import static jdk.vm.ci.sparc.SPARC.d54; -import static jdk.vm.ci.sparc.SPARC.d56; -import static jdk.vm.ci.sparc.SPARC.d58; -import static jdk.vm.ci.sparc.SPARC.d60; -import static jdk.vm.ci.sparc.SPARC.d62; -import static jdk.vm.ci.sparc.SPARC.f0; -import static jdk.vm.ci.sparc.SPARC.f10; -import static jdk.vm.ci.sparc.SPARC.f12; -import static jdk.vm.ci.sparc.SPARC.f14; -import static jdk.vm.ci.sparc.SPARC.f16; -import static jdk.vm.ci.sparc.SPARC.f18; -import static jdk.vm.ci.sparc.SPARC.f2; -import static jdk.vm.ci.sparc.SPARC.f20; -import static jdk.vm.ci.sparc.SPARC.f22; -import static jdk.vm.ci.sparc.SPARC.f24; -import static jdk.vm.ci.sparc.SPARC.f26; -import static jdk.vm.ci.sparc.SPARC.f28; -import static jdk.vm.ci.sparc.SPARC.f30; -import static jdk.vm.ci.sparc.SPARC.f4; -import static jdk.vm.ci.sparc.SPARC.f6; -import static jdk.vm.ci.sparc.SPARC.f8; -import static jdk.vm.ci.sparc.SPARC.g1; -import static jdk.vm.ci.sparc.SPARC.g3; -import static jdk.vm.ci.sparc.SPARC.g4; -import static jdk.vm.ci.sparc.SPARC.g5; import static jdk.vm.ci.sparc.SPARCKind.WORD; import static jdk.vm.ci.sparc.SPARCKind.XWORD; +import static org.graalvm.compiler.lir.LIRValueUtil.asConstant; +import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; -import java.util.Map; - +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.core.sparc.SPARCArithmeticLIRGenerator; import org.graalvm.compiler.core.sparc.SPARCLIRGenerator; +import org.graalvm.compiler.core.sparc.SPARCLIRKindTool; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; @@ -126,14 +87,13 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp final GraalHotSpotVMConfig config; private HotSpotDebugInfoBuilder debugInfoBuilder; - private LIRFrameState currentRuntimeCallInfo; public SPARCHotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes) { this(providers, config, lirGenRes, new ConstantTableBaseProvider()); } private SPARCHotSpotLIRGenerator(HotSpotProviders providers, GraalHotSpotVMConfig config, LIRGenerationResult lirGenRes, ConstantTableBaseProvider constantTableBaseProvider) { - this(new SPARCHotSpotLIRKindTool(), new SPARCArithmeticLIRGenerator(), new SPARCHotSpotMoveFactory(constantTableBaseProvider), providers, config, lirGenRes, constantTableBaseProvider); + this(new SPARCLIRKindTool(), new SPARCArithmeticLIRGenerator(), new SPARCHotSpotMoveFactory(constantTableBaseProvider), providers, config, lirGenRes, constantTableBaseProvider); } public SPARCHotSpotLIRGenerator(LIRKindTool lirKindTool, SPARCArithmeticLIRGenerator arithmeticLIRGen, MoveFactory moveFactory, HotSpotProviders providers, GraalHotSpotVMConfig config, @@ -196,12 +156,6 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp getResult().setMaxInterpreterFrameSize(debugInfoBuilder.maxInterpreterFrameSize()); } - @Override - protected void emitForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { - currentRuntimeCallInfo = info; - super.emitForeignCallOp(linkage, result, arguments, temps, info); - } - @Override public Variable emitForeignCall(ForeignCallLinkage linkage, LIRFrameState state, Value... args) { HotSpotForeignCallLinkage hotspotLinkage = (HotSpotForeignCallLinkage) linkage; @@ -280,7 +234,7 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp } @Override - public Variable emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { + public Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) { ValueKind kind = newValue.getValueKind(); assert kind.equals(expectedValue.getValueKind()); SPARCKind memKind = (SPARCKind) kind.getPlatformKind(); @@ -289,6 +243,15 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp return emitConditionalMove(memKind, expectedValue, result, Condition.EQ, true, trueValue, falseValue); } + @Override + public Variable emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue) { + ValueKind kind = newValue.getValueKind(); + assert kind.equals(expectedValue.getValueKind()); + Variable result = newVariable(newValue.getValueKind()); + append(new CompareAndSwapOp(result, asAllocatable(address), asAllocatable(expectedValue), asAllocatable(newValue))); + return result; + } + @Override public void emitPrefetchAllocate(Value address) { SPARCAddressValue addr = asAddressValue(address); @@ -349,8 +312,8 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp // metaspace pointer Variable result = newVariable(LIRKind.value(WORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0) { - base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.base)); + if (encoding.hasBase()) { + base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.getBase())); } append(new SPARCHotSpotMove.CompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -370,8 +333,8 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp // metaspace pointer Variable result = newVariable(LIRKind.value(XWORD)); AllocatableValue base = Value.ILLEGAL; - if (encoding.base != 0) { - base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.base)); + if (encoding.hasBase()) { + base = emitLoadConstant(LIRKind.value(XWORD), JavaConstant.forLong(encoding.getBase())); } append(new SPARCHotSpotMove.UncompressPointer(result, asAllocatable(pointer), base, encoding, nonNull)); return result; @@ -389,108 +352,6 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp return save; } - @Override - public SaveRegistersOp emitSaveAllRegisters() { - // We save all registers that were not saved by the save instruction. - // @formatter:off - Register[] savedRegisters = { - // CPU - g1, g3, g4, g5, - // FPU, use only every second register as doubles are stored anyways - f0, /*f1, */ f2, /*f3, */ f4, /*f5, */ f6, /*f7, */ - f8, /*f9, */ f10, /*f11,*/ f12, /*f13,*/ f14, /*f15,*/ - f16, /*f17,*/ f18, /*f19,*/ f20, /*f21,*/ f22, /*f23,*/ - f24, /*f25,*/ f26, /*f27,*/ f28, /*f29,*/ f30, /*f31 */ - d32, d34, d36, d38, - d40, d42, d44, d46, - d48, d50, d52, d54, - d56, d58, d60, d62 - }; - // @formatter:on - AllocatableValue[] savedRegisterLocations = new AllocatableValue[savedRegisters.length]; - for (int i = 0; i < savedRegisters.length; i++) { - PlatformKind kind = target().arch.getLargestStorableKind(savedRegisters[i].getRegisterCategory()); - VirtualStackSlot spillSlot = getResult().getFrameMapBuilder().allocateSpillSlot(LIRKind.value(kind)); - savedRegisterLocations[i] = spillSlot; - } - return emitSaveRegisters(savedRegisters, savedRegisterLocations, false); - } - - @Override - public void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) { - append(new SPARCHotSpotLeaveCurrentStackFrameOp()); - } - - @Override - public void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { - append(new SPARCHotSpotLeaveDeoptimizedStackFrameOp()); - } - - @Override - public void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp, SaveRegistersOp saveRegisterOp) { - Register thread = getProviders().getRegisters().getThreadRegister(); - Variable framePcVariable = load(framePc); - Variable senderSpVariable = load(senderSp); - Variable scratchVariable = newVariable(LIRKind.value(target().arch.getWordKind())); - append(new SPARCHotSpotEnterUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), framePcVariable, senderSpVariable, scratchVariable, - target().arch.getWordKind())); - } - - @Override - public void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) { - Register thread = getProviders().getRegisters().getThreadRegister(); - append(new SPARCHotSpotLeaveUnpackFramesStackFrameOp(thread, config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset())); - } - - @Override - public void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { - Variable frameSizeVariable = load(frameSize); - Variable framePcVariable = load(framePc); - Variable senderSpVariable = load(senderSp); - Variable initialInfoVariable = load(initialInfo); - append(new SPARCHotSpotPushInterpreterFrameOp(frameSizeVariable, framePcVariable, senderSpVariable, initialInfoVariable)); - } - - @Override - public Value emitUncommonTrapCall(Value trapRequest, Value mode, SaveRegistersOp saveRegisterOp) { - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(UNCOMMON_TRAP); - - Register threadRegister = getProviders().getRegisters().getThreadRegister(); - Value threadTemp = newVariable(LIRKind.value(target().arch.getWordKind())); - Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister(); - Variable spScratch = newVariable(LIRKind.value(target().arch.getWordKind())); - append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister, threadTemp, spScratch)); - Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(target().arch.getWordKind())), trapRequest, mode); - append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister, threadTemp)); - - Map calleeSaveInfo = getResult().getCalleeSaveInfo(); - assert currentRuntimeCallInfo != null; - assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); - calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); - - return result; - } - - @Override - public Value emitDeoptimizationFetchUnrollInfoCall(Value mode, SaveRegistersOp saveRegisterOp) { - ForeignCallLinkage linkage = getForeignCalls().lookupForeignCall(FETCH_UNROLL_INFO); - - Register threadRegister = getProviders().getRegisters().getThreadRegister(); - Value threadTemp = newVariable(LIRKind.value(target().arch.getWordKind())); - Register stackPointerRegister = getProviders().getRegisters().getStackPointerRegister(); - Variable spScratch = newVariable(LIRKind.value(target().arch.getWordKind())); - append(new SPARCHotSpotCRuntimeCallPrologueOp(config.threadLastJavaSpOffset(), threadRegister, stackPointerRegister, threadTemp, spScratch)); - Variable result = super.emitForeignCall(linkage, null, threadRegister.asValue(LIRKind.value(target().arch.getWordKind())), mode); - append(new SPARCHotSpotCRuntimeCallEpilogueOp(config.threadLastJavaSpOffset(), config.threadLastJavaPcOffset(), config.threadJavaFrameAnchorFlagsOffset(), threadRegister, threadTemp)); - - Map calleeSaveInfo = getResult().getCalleeSaveInfo(); - assert currentRuntimeCallInfo != null; - assert !calleeSaveInfo.containsKey(currentRuntimeCallInfo); - calleeSaveInfo.put(currentRuntimeCallInfo, saveRegisterOp); - - return result; - } - @Override public void emitNullCheck(Value address, LIRFrameState state) { PlatformKind kind = address.getPlatformKind(); @@ -527,7 +388,7 @@ public class SPARCHotSpotLIRGenerator extends SPARCLIRGenerator implements HotSp } @Override - protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue scratchValue) { + protected StrategySwitchOp createStrategySwitchOp(AllocatableValue base, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, Variable scratchValue) { return new SPARCHotSpotStrategySwitchOp(base, strategy, keyTargets, defaultTarget, key, scratchValue); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java deleted file mode 100644 index 99f3826f361..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.sparc; - -import static jdk.vm.ci.sparc.SPARC.g0; -import static jdk.vm.ci.sparc.SPARC.i0; -import static jdk.vm.ci.sparc.SPARC.l7; - -import org.graalvm.compiler.asm.sparc.SPARCAddress; -import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.Opcode; -import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -import org.graalvm.compiler.lir.sparc.SPARCLIRInstruction; -import org.graalvm.compiler.lir.sparc.SPARCSaveRegistersOp; - -import jdk.vm.ci.code.Register; - -/** - * Emits code that leaves a stack frame which is tailored to call the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@Opcode("LEAVE_UNPACK_FRAMES_STACK_FRAME") -final class SPARCHotSpotLeaveUnpackFramesStackFrameOp extends SPARCLIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotLeaveUnpackFramesStackFrameOp.class); - - private final Register thread; - private final int threadLastJavaSpOffset; - private final int threadLastJavaPcOffset; - private final int threadJavaFrameAnchorFlagsOffset; - - SPARCHotSpotLeaveUnpackFramesStackFrameOp(Register thread, int threadLastJavaSpOffset, int threadLastJavaPcOffset, int threadJavaFrameAnchorFlagsOffset) { - super(TYPE); - this.thread = thread; - this.threadLastJavaSpOffset = threadLastJavaSpOffset; - this.threadLastJavaPcOffset = threadLastJavaPcOffset; - this.threadJavaFrameAnchorFlagsOffset = threadJavaFrameAnchorFlagsOffset; - } - - @Override - public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { - /* - * Safe thread register manually since we are not using LEAF_SP for {@link - * DeoptimizationStub#UNPACK_FRAMES}. - */ - masm.mov(l7, thread); - - SPARCAddress lastJavaPc = new SPARCAddress(thread, threadLastJavaPcOffset); - - // We borrow the threads lastJavaPC to transfer the value from float to i0 - masm.stdf(SPARCSaveRegistersOp.RETURN_REGISTER_STORAGE, lastJavaPc); - masm.ldx(lastJavaPc, i0); - - // Clear last Java frame values. - masm.stx(g0, lastJavaPc); - masm.stx(g0, new SPARCAddress(thread, threadLastJavaSpOffset)); - masm.stw(g0, new SPARCAddress(thread, threadJavaFrameAnchorFlagsOffset)); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java index 7b869c46b9d..d6f9bdffaea 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMove.java @@ -38,7 +38,7 @@ import org.graalvm.compiler.asm.sparc.SPARCAssembler.CC; import org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler.ScratchRegister; -import org.graalvm.compiler.hotspot.CompressEncoding; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.StandardOp.LoadConstantOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; @@ -146,7 +146,7 @@ public class SPARCHotSpotMove { public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) { Register inputRegister = asRegister(input); Register resReg = asRegister(result); - if (encoding.base != 0) { + if (encoding.hasBase()) { Register baseReg = asRegister(baseRegister); if (!nonNull) { masm.cmp(inputRegister, baseReg); @@ -155,11 +155,11 @@ public class SPARCHotSpotMove { } else { masm.sub(inputRegister, baseReg, resReg); } - if (encoding.shift != 0) { - masm.srlx(resReg, encoding.shift, resReg); + if (encoding.getShift() != 0) { + masm.srlx(resReg, encoding.getShift(), resReg); } } else { - masm.srlx(inputRegister, encoding.shift, resReg); + masm.srlx(inputRegister, encoding.getShift(), resReg); } } } @@ -189,14 +189,14 @@ public class SPARCHotSpotMove { Register inputRegister = asRegister(input); Register resReg = asRegister(result); Register secondaryInput; - if (encoding.shift != 0) { - masm.sll(inputRegister, encoding.shift, resReg); + if (encoding.getShift() != 0) { + masm.sll(inputRegister, encoding.getShift(), resReg); secondaryInput = resReg; } else { secondaryInput = inputRegister; } - if (encoding.base != 0) { + if (encoding.hasBase()) { if (nonNull) { masm.add(secondaryInput, asRegister(baseRegister), resReg); } else { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMoveFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMoveFactory.java index 80545e36944..0be5caf20c9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMoveFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotMoveFactory.java @@ -32,10 +32,10 @@ import org.graalvm.compiler.lir.LIRInstruction; import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; import jdk.vm.ci.hotspot.HotSpotConstant; +import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaConstant; public class SPARCHotSpotMoveFactory extends SPARCMoveFactory { @@ -44,10 +44,10 @@ public class SPARCHotSpotMoveFactory extends SPARCMoveFactory { } @Override - public boolean canInlineConstant(JavaConstant c) { + public boolean canInlineConstant(Constant c) { if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(c)) { return true; - } else if (c instanceof HotSpotObjectConstant) { + } else if (c instanceof HotSpotObjectConstant || c instanceof HotSpotMetaspaceConstant) { return false; } else { return super.canInlineConstant(c); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeCostProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeCostProvider.java deleted file mode 100644 index d2c3eca7968..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeCostProvider.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.sparc; - -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.hotspot.nodes.HotSpotNodeCostProvider; -import org.graalvm.compiler.hotspot.nodes.JumpToExceptionHandlerNode; -import org.graalvm.compiler.nodeinfo.NodeCycles; -import org.graalvm.compiler.nodeinfo.NodeSize; -import org.graalvm.compiler.nodes.ReturnNode; - -public class SPARCHotSpotNodeCostProvider extends HotSpotNodeCostProvider { - - @Override - public NodeCycles cycles(Node n) { - if (n instanceof ReturnNode) { - return NodeCycles.CYCLES_6; - } else if (n instanceof JumpToExceptionHandlerNode) { - // restore caller window - return NodeCycles.CYCLES_3; - } - return super.cycles(n); - } - - @Override - public NodeSize size(Node n) { - if (n instanceof ReturnNode) { - return NodeSize.SIZE_4; - } else if (n instanceof JumpToExceptionHandlerNode) { - // restore caller window - return NodeSize.SIZE_3; - } - return super.size(n); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java index e16abf52bd2..414058f9e67 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotNodeLIRBuilder.java @@ -22,28 +22,25 @@ */ package org.graalvm.compiler.hotspot.sparc; -import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; import static jdk.vm.ci.sparc.SPARC.g5; import static jdk.vm.ci.sparc.SPARC.o7; +import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER_IN_CALLER; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.gen.DebugInfoBuilder; import org.graalvm.compiler.core.sparc.SPARCNodeLIRBuilder; import org.graalvm.compiler.core.sparc.SPARCNodeMatchRules; -import org.graalvm.compiler.debug.Debug; import org.graalvm.compiler.hotspot.HotSpotDebugInfoBuilder; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; import org.graalvm.compiler.hotspot.HotSpotLockStack; import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import org.graalvm.compiler.lir.sparc.SPARCBreakpointOp; -import org.graalvm.compiler.lir.sparc.SPARCMove.CompareAndSwapOp; import org.graalvm.compiler.nodes.BreakpointNode; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; import org.graalvm.compiler.nodes.DirectCallTargetNode; @@ -90,18 +87,6 @@ public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements H append(new SPARCHotSpotSafepointOp(info, getGen().config, gen)); } - @Override - public void visitDirectCompareAndSwap(DirectCompareAndSwapNode x) { - AllocatableValue address = gen.asAllocatable(operand(x.getAddress())); - AllocatableValue cmpValue = gen.asAllocatable(operand(x.expectedValue())); - AllocatableValue newValue = gen.asAllocatable(operand(x.newValue())); - assert cmpValue.getValueKind().equals(newValue.getValueKind()); - - Variable result = gen.newVariable(newValue.getValueKind()); - append(new CompareAndSwapOp(result, address, cmpValue, newValue)); - setResult(x, result); - } - @Override protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) { InvokeKind invokeKind = ((HotSpotDirectCallTargetNode) callTarget).invokeKind(); @@ -164,7 +149,7 @@ public class SPARCHotSpotNodeLIRBuilder extends SPARCNodeLIRBuilder implements H @Override public void visitFullInfopointNode(FullInfopointNode i) { if (i.getState() != null && i.getState().bci == BytecodeFrame.AFTER_BCI) { - Debug.log("Ignoring InfopointNode for AFTER_BCI"); + i.getDebug().log("Ignoring InfopointNode for AFTER_BCI"); } else { super.visitFullInfopointNode(i); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotRegisterAllocationConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotRegisterAllocationConfig.java index 85fd975a91d..0265525c17e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotRegisterAllocationConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotRegisterAllocationConfig.java @@ -112,8 +112,8 @@ public class SPARCHotSpotRegisterAllocationConfig extends RegisterAllocationConf }; // @formatter:on - public SPARCHotSpotRegisterAllocationConfig(RegisterConfig registerConfig) { - super(registerConfig); + public SPARCHotSpotRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) { + super(registerConfig, allocationRestrictedTo); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java index fedd4a13673..f4e2c741782 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotStrategySwitchOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -22,14 +22,14 @@ */ package org.graalvm.compiler.hotspot.sparc; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.sparc.SPARC.g0; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CBCOND; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.INSTRUCTION_SIZE; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.ANNUL; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict.PREDICT_TAKEN; import static org.graalvm.compiler.lir.sparc.SPARCMove.loadFromConstantTable; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARC.g0; import org.graalvm.compiler.asm.Assembler.LabelHint; import org.graalvm.compiler.asm.Label; @@ -40,6 +40,7 @@ import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.LabelRef; import org.graalvm.compiler.lir.SwitchStrategy; +import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.sparc.SPARCControlFlow; import org.graalvm.compiler.lir.sparc.SPARCDelayedControlTransfer; @@ -54,7 +55,7 @@ import jdk.vm.ci.sparc.SPARC.CPUFeature; final class SPARCHotSpotStrategySwitchOp extends SPARCControlFlow.StrategySwitchOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCHotSpotStrategySwitchOp.class); - SPARCHotSpotStrategySwitchOp(Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Value key, Value scratch) { + SPARCHotSpotStrategySwitchOp(Value constantTableBase, SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, AllocatableValue key, Variable scratch) { super(TYPE, constantTableBase, strategy, keyTargets, defaultTarget, key, scratch); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCUncommonTrapStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCUncommonTrapStub.java deleted file mode 100644 index 3ef27516389..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCUncommonTrapStub.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.sparc; - -import static jdk.vm.ci.sparc.SPARC.g1; -import static jdk.vm.ci.sparc.SPARC.g3; -import static jdk.vm.ci.sparc.SPARC.g4; -import static jdk.vm.ci.sparc.SPARC.g5; -import static jdk.vm.ci.sparc.SPARC.o0; -import static jdk.vm.ci.sparc.SPARC.o1; -import static jdk.vm.ci.sparc.SPARC.o2; -import static jdk.vm.ci.sparc.SPARC.o3; -import static jdk.vm.ci.sparc.SPARC.o4; - -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.UncommonTrapStub; - -import jdk.vm.ci.code.RegisterArray; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.sparc.SPARCHotSpotRegisterConfig; - -final class SPARCUncommonTrapStub extends UncommonTrapStub { - - private RegisterConfig registerConfig; - - SPARCUncommonTrapStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(providers, target, linkage); - // This is basically the maximum we can spare. All other G and O register are used. - RegisterArray allocatable = new RegisterArray(g1, g3, g4, g5, o0, o1, o2, o3, o4); - registerConfig = new SPARCHotSpotRegisterConfig(target, allocatable); - } - - @Override - public RegisterConfig getRegisterConfig() { - return registerConfig; - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java index ec528b1c6f9..a08edd079c0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/AheadOfTimeCompilationTest.java @@ -22,39 +22,29 @@ */ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.core.GraalCompiler.compileGraph; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; - -import org.graalvm.compiler.api.test.Graal; -import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; -import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory; -import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.memory.FloatingReadNode; import org.graalvm.compiler.nodes.memory.ReadNode; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; -import org.graalvm.compiler.phases.OptimisticOptimizations; -import org.graalvm.compiler.phases.tiers.Suites; -import org.graalvm.compiler.phases.tiers.SuitesProvider; -import org.graalvm.compiler.runtime.RuntimeProvider; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; +import jdk.vm.ci.aarch64.AArch64; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaMethod; /** * use @@ -74,14 +64,19 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { return AheadOfTimeCompilationTest.STATICFINALOBJECT; } + @Before + public void setUp() { + // Ignore on SPARC + Assume.assumeFalse("skipping on AArch64", getTarget().arch instanceof AArch64); + } + @Test public void testStaticFinalObjectAOT() { StructuredGraph result = compile("getStaticFinalObject", true); assertDeepEquals(1, getConstantNodes(result).count()); Stamp constantStamp = getConstantNodes(result).first().stamp(); Assert.assertTrue(constantStamp.toString(), constantStamp instanceof KlassPointerStamp); - assertDeepEquals(2, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); + assertDeepEquals(2, result.getNodes().filter(ReadNode.class).count()); } @Test @@ -89,7 +84,6 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { StructuredGraph result = compile("getStaticFinalObject", false); assertDeepEquals(1, getConstantNodes(result).count()); assertDeepEquals(JavaKind.Object, getConstantNodes(result).first().getStackKind()); - assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); } @@ -106,8 +100,7 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) getMetaAccess().lookupJavaType(AheadOfTimeCompilationTest.class); assertDeepEquals(type.klass(), filter.first().asConstant()); - assertDeepEquals(1, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); + assertDeepEquals(1, result.getNodes().filter(ReadNode.class).count()); } @Test @@ -119,7 +112,6 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { JavaConstant c = filter.first().asJavaConstant(); Assert.assertEquals(getSnippetReflection().asObject(Class.class, c), AheadOfTimeCompilationTest.class); - assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); } @@ -135,8 +127,7 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { Stamp constantStamp = filter.first().stamp(); Assert.assertTrue(constantStamp instanceof KlassPointerStamp); - assertDeepEquals(2, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); + assertDeepEquals(2, result.getNodes().filter(ReadNode.class).count()); } @Test @@ -147,7 +138,6 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { JavaConstant c = filter.first().asJavaConstant(); Assert.assertEquals(getSnippetReflection().asObject(Class.class, c), Integer.TYPE); - assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); assertDeepEquals(0, result.getNodes().filter(ReadNode.class).count()); } @@ -182,17 +172,18 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { return Boolean.valueOf(true); } - @Ignore("ImmutableCode override may not work reliably in non-hosted mode") @Test public void testBoxedBooleanAOT() { StructuredGraph result = compile("getBoxedBoolean", true); - assertDeepEquals(2, result.getNodes().filter(FloatingReadNode.class).count()); - assertDeepEquals(1, result.getNodes(PiNode.TYPE).count()); + assertDeepEquals(0, result.getNodes().filter(FloatingReadNode.class).count()); + assertDeepEquals(0, result.getNodes(PiNode.TYPE).count()); assertDeepEquals(1, getConstantNodes(result).count()); ConstantNode constant = getConstantNodes(result).first(); - assertDeepEquals(JavaKind.Long, constant.getStackKind()); - assertDeepEquals(((HotSpotResolvedObjectType) getMetaAccess().lookupJavaType(Boolean.class)).klass(), constant.asConstant()); + assertDeepEquals(JavaKind.Object, constant.getStackKind()); + + JavaConstant c = constant.asJavaConstant(); + Assert.assertEquals(getSnippetReflection().asObject(Boolean.class, c), Boolean.TRUE); } @Test @@ -210,17 +201,9 @@ public class AheadOfTimeCompilationTest extends GraalCompilerTest { @SuppressWarnings("try") private StructuredGraph compile(String test, boolean compileAOT) { - try (OverrideScope s = OptionValue.override(ImmutableCode, compileAOT)) { - StructuredGraph graph = parseEager(test, AllowAssumptions.YES); - ResolvedJavaMethod method = graph.method(); - // create suites everytime, as we modify options for the compiler - SuitesProvider suitesProvider = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getSuites(); - final Suites suitesLocal = suitesProvider.getDefaultSuites(); - final LIRSuites lirSuitesLocal = suitesProvider.getDefaultLIRSuites(); - final CompilationResult compResult = compileGraph(graph, method, getProviders(), getBackend(), getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, graph.getProfilingInfo(), - suitesLocal, lirSuitesLocal, new CompilationResult(), CompilationResultBuilderFactory.Default); - addMethod(method, compResult); - return graph; - } + OptionValues options = new OptionValues(getInitialOptions(), ImmutableCode, compileAOT); + StructuredGraph graph = parseEager(test, AllowAssumptions.YES, options); + compile(graph.method(), graph); + return graph; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java index e3ea0bc743b..952dd2bc08e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ArrayCopyIntrinsificationTest.java @@ -26,9 +26,6 @@ import java.lang.reflect.Array; import java.util.ArrayList; import java.util.HashMap; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.replacements.arraycopy.ArrayCopySnippets; @@ -36,6 +33,9 @@ import org.graalvm.compiler.nodes.DirectCallTargetNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.LoweredCallTargetNode; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; +import org.junit.Test; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.JavaMethod; @@ -47,10 +47,10 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class ArrayCopyIntrinsificationTest extends GraalCompilerTest { @Override - protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph g) { + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph g, boolean forceCompile, boolean installAsDefault, OptionValues options) { StructuredGraph graph = g == null ? parseForCompile(method) : g; int nodeCount = graph.getNodeCount(); - InstalledCode result = super.getCode(method, graph); + InstalledCode result = super.getCode(method, graph, forceCompile, installAsDefault, options); boolean graphWasProcessed = nodeCount != graph.getNodeCount(); if (graphWasProcessed) { if (mustIntrinsify) { @@ -160,7 +160,7 @@ public class ArrayCopyIntrinsificationTest extends GraalCompilerTest { } /** - * Tests {@link ArrayCopySnippets#checkcastArraycopyWork(Object, int, Object, int, int)}. + * Tests {@link ArrayCopySnippets#checkcastArraycopyWork}. */ @Test public void testArrayStoreException() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java index 9a73893a4f5..846c55e404f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -22,15 +22,12 @@ */ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.core.common.util.Util.JAVA_SPECIFICATION_VERSION; - import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.stream.Collectors; @@ -44,7 +41,10 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.graalvm.compiler.serviceprovider.JDK9Method; import org.graalvm.compiler.test.GraalTest; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.MapCursor; import org.junit.Test; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; @@ -55,11 +55,10 @@ import jdk.vm.ci.meta.MethodHandleAccessProvider.IntrinsicMethod; import jdk.vm.ci.meta.ResolvedJavaMethod; /** - * Checks the set of intrinsics implemented by Graal against the set of intrinsics declared by - * HotSpot. The purpose of this test is to detect when new intrinsics are added to HotSpot and - * process them appropriately in Graal. This will be achieved by working through - * {@link #TO_BE_INVESTIGATED} and either implementing the intrinsic or moving it to {@link #IGNORE} - * . + * Checks the intrinsics implemented by Graal against the set of intrinsics declared by HotSpot. The + * purpose of this test is to detect when new intrinsics are added to HotSpot and process them + * appropriately in Graal. This will be achieved by working through {@link #TO_BE_INVESTIGATED} and + * either implementing the intrinsic or moving it to {@link #IGNORE} . */ public class CheckGraalIntrinsics extends GraalTest { @@ -74,11 +73,12 @@ public class CheckGraalIntrinsics extends GraalTest { return false; } - public static InvocationPlugin findPlugin(Map> bindings, VMIntrinsicMethod intrinsic) { - for (Map.Entry> e : bindings.entrySet()) { + public static InvocationPlugin findPlugin(EconomicMap> bindings, VMIntrinsicMethod intrinsic) { + MapCursor> cursor = bindings.getEntries(); + while (cursor.advance()) { // Match format of VMIntrinsicMethod.declaringClass - String type = MetaUtil.internalNameToJava(e.getKey(), true, false).replace('.', '/'); - for (Binding binding : e.getValue()) { + String type = MetaUtil.internalNameToJava(cursor.getKey(), true, false).replace('.', '/'); + for (Binding binding : cursor.getValue()) { if (match(type, binding, intrinsic)) { return binding.plugin; } @@ -88,7 +88,19 @@ public class CheckGraalIntrinsics extends GraalTest { } public static ResolvedJavaMethod resolveIntrinsic(MetaAccessProvider metaAccess, VMIntrinsicMethod intrinsic) throws ClassNotFoundException { - Class c = Class.forName(intrinsic.declaringClass.replace('/', '.'), false, CheckGraalIntrinsics.class.getClassLoader()); + Class c; + try { + c = Class.forName(intrinsic.declaringClass.replace('/', '.'), false, CheckGraalIntrinsics.class.getClassLoader()); + } catch (ClassNotFoundException ex) { + try { + Class.forName("javax.naming.Reference"); + } catch (ClassNotFoundException coreNamingMissing) { + // if core JDK classes aren't found, we are probably running in a + // JDK9 java.base environment and then missing class is OK + return null; + } + throw ex; + } for (Method javaMethod : c.getDeclaredMethods()) { if (javaMethod.getName().equals(intrinsic.name)) { ResolvedJavaMethod method = metaAccess.lookupJavaMethod(javaMethod); @@ -244,21 +256,21 @@ public class CheckGraalIntrinsics extends GraalTest { "java/util/zip/Adler32.updateByteBuffer(IJII)I", "java/util/zip/Adler32.updateBytes(I[BII)I", "jdk/internal/misc/Unsafe.allocateUninitializedArray0(Ljava/lang/Class;I)Ljava/lang/Object;", + "jdk/internal/misc/Unsafe.compareAndExchangeByte(Ljava/lang/Object;JBB)B", "jdk/internal/misc/Unsafe.compareAndExchangeByteAcquire(Ljava/lang/Object;JBB)B", "jdk/internal/misc/Unsafe.compareAndExchangeByteRelease(Ljava/lang/Object;JBB)B", - "jdk/internal/misc/Unsafe.compareAndExchangeByte(Ljava/lang/Object;JBB)B", + "jdk/internal/misc/Unsafe.compareAndExchangeInt(Ljava/lang/Object;JII)I", "jdk/internal/misc/Unsafe.compareAndExchangeIntAcquire(Ljava/lang/Object;JII)I", "jdk/internal/misc/Unsafe.compareAndExchangeIntRelease(Ljava/lang/Object;JII)I", - "jdk/internal/misc/Unsafe.compareAndExchangeInt(Ljava/lang/Object;JII)I", + "jdk/internal/misc/Unsafe.compareAndExchangeLong(Ljava/lang/Object;JJJ)J", "jdk/internal/misc/Unsafe.compareAndExchangeLongAcquire(Ljava/lang/Object;JJJ)J", "jdk/internal/misc/Unsafe.compareAndExchangeLongRelease(Ljava/lang/Object;JJJ)J", - "jdk/internal/misc/Unsafe.compareAndExchangeLong(Ljava/lang/Object;JJJ)J", + "jdk/internal/misc/Unsafe.compareAndExchangeObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", "jdk/internal/misc/Unsafe.compareAndExchangeObjectAcquire(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", "jdk/internal/misc/Unsafe.compareAndExchangeObjectRelease(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", - "jdk/internal/misc/Unsafe.compareAndExchangeObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", + "jdk/internal/misc/Unsafe.compareAndExchangeShort(Ljava/lang/Object;JSS)S", "jdk/internal/misc/Unsafe.compareAndExchangeShortAcquire(Ljava/lang/Object;JSS)S", "jdk/internal/misc/Unsafe.compareAndExchangeShortRelease(Ljava/lang/Object;JSS)S", - "jdk/internal/misc/Unsafe.compareAndExchangeShort(Ljava/lang/Object;JSS)S", "jdk/internal/misc/Unsafe.compareAndSetByte(Ljava/lang/Object;JBB)Z", "jdk/internal/misc/Unsafe.compareAndSetShort(Ljava/lang/Object;JSS)Z", "jdk/internal/misc/Unsafe.copyMemory0(Ljava/lang/Object;JLjava/lang/Object;JJ)V", @@ -295,26 +307,26 @@ public class CheckGraalIntrinsics extends GraalTest { "jdk/internal/misc/Unsafe.putObjectOpaque(Ljava/lang/Object;JLjava/lang/Object;)V", "jdk/internal/misc/Unsafe.putShortOpaque(Ljava/lang/Object;JS)V", "jdk/internal/misc/Unsafe.unpark(Ljava/lang/Object;)V", - "jdk/internal/misc/Unsafe.weakCompareAndSetBytePlain(Ljava/lang/Object;JBB)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetByteAcquire(Ljava/lang/Object;JBB)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetByteRelease(Ljava/lang/Object;JBB)Z", "jdk/internal/misc/Unsafe.weakCompareAndSetByte(Ljava/lang/Object;JBB)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetIntPlain(Ljava/lang/Object;JII)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetIntAcquire(Ljava/lang/Object;JII)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetIntRelease(Ljava/lang/Object;JII)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetByteAcquire(Ljava/lang/Object;JBB)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetBytePlain(Ljava/lang/Object;JBB)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetByteRelease(Ljava/lang/Object;JBB)Z", "jdk/internal/misc/Unsafe.weakCompareAndSetInt(Ljava/lang/Object;JII)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetLongPlain(Ljava/lang/Object;JJJ)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetLongAcquire(Ljava/lang/Object;JJJ)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetLongRelease(Ljava/lang/Object;JJJ)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetIntAcquire(Ljava/lang/Object;JII)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetIntPlain(Ljava/lang/Object;JII)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetIntRelease(Ljava/lang/Object;JII)Z", "jdk/internal/misc/Unsafe.weakCompareAndSetLong(Ljava/lang/Object;JJJ)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetObjectPlain(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetObjectAcquire(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetObjectRelease(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetLongAcquire(Ljava/lang/Object;JJJ)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetLongPlain(Ljava/lang/Object;JJJ)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetLongRelease(Ljava/lang/Object;JJJ)Z", "jdk/internal/misc/Unsafe.weakCompareAndSetObject(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetShortPlain(Ljava/lang/Object;JSS)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetShortAcquire(Ljava/lang/Object;JSS)Z", - "jdk/internal/misc/Unsafe.weakCompareAndSetShortRelease(Ljava/lang/Object;JSS)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetObjectAcquire(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetObjectPlain(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetObjectRelease(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", "jdk/internal/misc/Unsafe.weakCompareAndSetShort(Ljava/lang/Object;JSS)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetShortAcquire(Ljava/lang/Object;JSS)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetShortPlain(Ljava/lang/Object;JSS)Z", + "jdk/internal/misc/Unsafe.weakCompareAndSetShortRelease(Ljava/lang/Object;JSS)Z", "jdk/internal/util/Preconditions.checkIndex(IILjava/util/function/BiFunction;)I", "jdk/jfr/internal/JVM.counterTime()J", "jdk/jfr/internal/JVM.getBufferWriter()Ljava/lang/Object;", @@ -368,7 +380,7 @@ public class CheckGraalIntrinsics extends GraalTest { if (!config.useCRC32Intrinsics) { // Registration of the CRC32 plugins is guarded by UseCRC32Intrinsics add(IGNORE, "java/util/zip/CRC32.update(II)I"); - if (JAVA_SPECIFICATION_VERSION < 9) { + if (JDK9Method.JAVA_SPECIFICATION_VERSION < 9) { add(IGNORE, "java/util/zip/CRC32.updateByteBuffer(IJII)I", "java/util/zip/CRC32.updateBytes(I[BII)I"); @@ -380,7 +392,7 @@ public class CheckGraalIntrinsics extends GraalTest { "java/util/zip/CRC32C.updateDirectByteBuffer(IJII)I"); } } else { - if (JAVA_SPECIFICATION_VERSION >= 9) { + if (JDK9Method.JAVA_SPECIFICATION_VERSION >= 9) { add(TO_BE_INVESTIGATED, "java/util/zip/CRC32C.updateBytes(I[BII)I", "java/util/zip/CRC32C.updateDirectByteBuffer(IJII)I"); @@ -389,7 +401,7 @@ public class CheckGraalIntrinsics extends GraalTest { if (!config.useAESIntrinsics) { // Registration of the AES plugins is guarded by UseAESIntrinsics - if (JAVA_SPECIFICATION_VERSION < 9) { + if (JDK9Method.JAVA_SPECIFICATION_VERSION < 9) { add(IGNORE, "com/sun/crypto/provider/AESCrypt.decryptBlock([BI[BI)V", "com/sun/crypto/provider/AESCrypt.encryptBlock([BI[BI)V", @@ -405,7 +417,7 @@ public class CheckGraalIntrinsics extends GraalTest { } if (!config.useMultiplyToLenIntrinsic()) { // Registration of the AES plugins is guarded by UseAESIntrinsics - if (JAVA_SPECIFICATION_VERSION < 9) { + if (JDK9Method.JAVA_SPECIFICATION_VERSION < 9) { add(IGNORE, "java/math/BigInteger.multiplyToLen([II[II[I)[I"); } else { add(IGNORE, "java/math/BigInteger.implMultiplyToLen([II[II[I)[I"); @@ -435,7 +447,7 @@ public class CheckGraalIntrinsics extends GraalTest { List intrinsics = store.getIntrinsics(); List missing = new ArrayList<>(); - Map> bindings = invocationPlugins.getBindings(true); + EconomicMap> bindings = invocationPlugins.getBindings(true); for (VMIntrinsicMethod intrinsic : intrinsics) { InvocationPlugin plugin = findPlugin(bindings, intrinsic); if (plugin == null) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ClassSubstitutionsTests.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ClassSubstitutionsTests.java index 7b22ece7897..70cb998a215 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ClassSubstitutionsTests.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ClassSubstitutionsTests.java @@ -23,16 +23,14 @@ package org.graalvm.compiler.hotspot.test; -import org.junit.Test; - import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.junit.Test; public class ClassSubstitutionsTests extends GraalCompilerTest { @@ -44,14 +42,15 @@ public class ClassSubstitutionsTests extends GraalCompilerTest { @SuppressWarnings("try") protected StructuredGraph test(final String snippet) { - try (Scope s = Debug.scope("ClassSubstitutionsTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { - StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("ClassSubstitutionsTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug); compile(graph.method(), graph); assertNotInGraph(graph, Invoke.class); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet); + debug.dump(DebugContext.BASIC_LEVEL, graph, snippet); return graph; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java new file mode 100644 index 00000000000..b75ec2da97f --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.test; + +import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine; +import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; + +import org.graalvm.compiler.core.GraalCompilerOptions; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.test.SubprocessUtil; +import org.graalvm.compiler.test.SubprocessUtil.Subprocess; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; + +/** + * Tests support for dumping graphs and other info useful for debugging a compiler crash. + */ +public class CompilationWrapperTest extends GraalCompilerTest { + public CompilationWrapperTest() { + try { + Class.forName("java.lang.management.ManagementFactory"); + } catch (ClassNotFoundException ex) { + Assume.assumeNoException("skip this test if there is no java.management JDK9 module around", ex); + } + } + + /** + * Tests compilation requested by the VM. + */ + @Test + public void testVMCompilation1() throws IOException, InterruptedException { + testHelper(Collections.emptyList(), Arrays.asList("-XX:+BootstrapJVMCI", + "-XX:+UseJVMCICompiler", + "-Dgraal.CompilationFailureAction=ExitVM", + "-Dgraal.CrashAt=Object.*,String.*", + "-version")); + } + + /** + * Tests that {@code -Dgraal.ExitVMOnException=true} works as an alias for + * {@code -Dgraal.CompilationFailureAction=ExitVM}. + */ + @Test + public void testVMCompilation2() throws IOException, InterruptedException { + testHelper(Collections.emptyList(), Arrays.asList("-XX:+BootstrapJVMCI", + "-XX:+UseJVMCICompiler", + "-Dgraal.ExitVMOnException=true", + "-Dgraal.CrashAt=Object.*,String.*", + "-version")); + } + + static class Probe { + final String substring; + final int expectedOccurrences; + int actualOccurrences; + String lastMatchingLine; + + Probe(String substring, int expectedOccurrences) { + this.substring = substring; + this.expectedOccurrences = expectedOccurrences; + } + + boolean matches(String line) { + if (line.contains(substring)) { + actualOccurrences++; + lastMatchingLine = line; + return true; + } + return false; + } + + String test() { + return expectedOccurrences == actualOccurrences ? null : String.format("expected %d, got %d occurrences", expectedOccurrences, actualOccurrences); + } + } + + /** + * Tests {@link GraalCompilerOptions#MaxCompilationProblemsPerAction} in context of a + * compilation requested by the VM. + */ + @Test + public void testVMCompilation3() throws IOException, InterruptedException { + final int maxProblems = 4; + Probe[] probes = { + new Probe("To capture more information for diagnosing or reporting a compilation", maxProblems), + new Probe("Retrying compilation of", maxProblems), + new Probe("adjusting CompilationFailureAction from Diagnose to Print", 1), + new Probe("adjusting CompilationFailureAction from Print to Silent", 1), + }; + testHelper(Arrays.asList(probes), Arrays.asList("-XX:+BootstrapJVMCI", + "-XX:+UseJVMCICompiler", + "-Dgraal.CompilationFailureAction=Diagnose", + "-Dgraal.MaxCompilationProblemsPerAction=" + maxProblems, + "-Dgraal.CrashAt=Object.*,String.*", + "-version")); + } + + /** + * Tests compilation requested by Truffle. + */ + @Test + public void testTruffleCompilation() throws IOException, InterruptedException { + testHelper(Collections.emptyList(), + Arrays.asList( + "-Dgraal.CompilationFailureAction=ExitVM", + "-Dgraal.CrashAt=root test1"), + "org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", "test"); + } + + private static final boolean VERBOSE = Boolean.getBoolean(CompilationWrapperTest.class.getSimpleName() + ".verbose"); + + private static void testHelper(List initialProbes, List extraVmArgs, String... mainClassAndArgs) throws IOException, InterruptedException { + final File dumpPath = new File(CompilationWrapperTest.class.getSimpleName() + "_" + System.currentTimeMillis()).getAbsoluteFile(); + List vmArgs = withoutDebuggerArguments(getVMCommandLine()); + vmArgs.removeIf(a -> a.startsWith("-Dgraal.")); + vmArgs.remove("-esa"); + vmArgs.remove("-ea"); + vmArgs.add("-Dgraal.DumpPath=" + dumpPath); + // Force output to a file even if there's a running IGV instance available. + vmArgs.add("-Dgraal.PrintGraphFile=true"); + vmArgs.addAll(extraVmArgs); + + Subprocess proc = SubprocessUtil.java(vmArgs, mainClassAndArgs); + if (VERBOSE) { + System.out.println(proc); + } + + List probes = new ArrayList<>(initialProbes); + Probe diagnosticProbe = new Probe("Graal diagnostic output saved in ", 1); + probes.add(diagnosticProbe); + probes.add(new Probe("Forced crash after compiling", Integer.MAX_VALUE) { + @Override + String test() { + return actualOccurrences > 0 ? null : "expected at least 1 occurrence"; + } + }); + + for (String line : proc.output) { + for (Probe probe : probes) { + if (probe.matches(line)) { + break; + } + } + } + for (Probe probe : probes) { + String error = probe.test(); + if (error != null) { + Assert.fail(String.format("Did not find expected occurences of '%s' in output of command: %s%n%s", probe.substring, error, proc)); + } + } + + String diagnosticOutputZip = diagnosticProbe.lastMatchingLine.substring(diagnosticProbe.substring.length()).trim(); + + List dumpPathEntries = Arrays.asList(dumpPath.list()); + + File zip = new File(diagnosticOutputZip).getAbsoluteFile(); + Assert.assertTrue(zip.toString(), zip.exists()); + Assert.assertTrue(zip + " not in " + dumpPathEntries, dumpPathEntries.contains(zip.getName())); + try { + int bgv = 0; + int cfg = 0; + ZipFile dd = new ZipFile(diagnosticOutputZip); + List entries = new ArrayList<>(); + for (Enumeration e = dd.entries(); e.hasMoreElements();) { + ZipEntry ze = e.nextElement(); + String name = ze.getName(); + entries.add(name); + if (name.endsWith(".bgv")) { + bgv++; + } else if (name.endsWith(".cfg")) { + cfg++; + } + } + if (bgv == 0) { + Assert.fail(String.format("Expected at least one .bgv file in %s: %s%n%s", diagnosticOutputZip, entries, proc)); + } + if (cfg == 0) { + Assert.fail(String.format("Expected at least one .cfg file in %s: %s", diagnosticOutputZip, entries)); + } + } finally { + zip.delete(); + dumpPath.delete(); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorld.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java similarity index 63% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorld.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java index b2542607a3f..abd9455ec13 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorld.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java @@ -20,19 +20,16 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package org.graalvm.compiler.hotspot; +package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException; -import static org.graalvm.compiler.core.GraalCompilerOptions.PrintBailout; -import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException; -import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier; -import static org.graalvm.compiler.hotspot.CompileTheWorldOptions.CompileTheWorldClasspath; -import static org.graalvm.compiler.hotspot.CompileTheWorldOptions.CompileTheWorldConfig; -import static org.graalvm.compiler.hotspot.CompileTheWorldOptions.CompileTheWorldExcludeMethodFilter; -import static org.graalvm.compiler.hotspot.CompileTheWorldOptions.CompileTheWorldMethodFilter; -import static org.graalvm.compiler.hotspot.CompileTheWorldOptions.CompileTheWorldStartAt; -import static org.graalvm.compiler.hotspot.CompileTheWorldOptions.CompileTheWorldStopAt; -import static org.graalvm.compiler.hotspot.CompileTheWorldOptions.CompileTheWorldVerbose; +import static java.util.Collections.singletonList; +import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Print; +import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction; +import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction; +import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries; +import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes; +import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS; +import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; import java.io.Closeable; import java.io.File; @@ -41,26 +38,22 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.net.URI; import java.net.URL; import java.net.URLClassLoader; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; +import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardOpenOption; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.Enumeration; -import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.ServiceLoader; import java.util.Set; import java.util.concurrent.ExecutionException; @@ -76,22 +69,24 @@ import java.util.stream.Collectors; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.bytecode.Bytecodes; import org.graalvm.compiler.core.CompilerThreadFactory; -import org.graalvm.compiler.core.CompilerThreadFactory.DebugConfigAccess; -import org.graalvm.compiler.core.common.util.Util; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugEnvironment; -import org.graalvm.compiler.debug.GraalDebugConfig; +import org.graalvm.compiler.core.test.ReflectionOptionDescriptors; +import org.graalvm.compiler.debug.DebugOptions; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.MethodFilter; import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.DebugScope; -import org.graalvm.compiler.debug.internal.MemUseTrackerImpl; -import org.graalvm.compiler.options.OptionDescriptor; +import org.graalvm.compiler.hotspot.CompilationTask; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; +import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.options.OptionDescriptors; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionsParser; -import org.graalvm.compiler.options.OptionsParser.OptionConsumer; +import org.graalvm.compiler.serviceprovider.JDK9Method; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.UnmodifiableEconomicMap; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotInstalledCode; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -109,55 +104,35 @@ import jdk.vm.ci.runtime.JVMCICompiler; public final class CompileTheWorld { /** - * Magic token to denote that JDK classes are to be compiled. If {@link Util#Java8OrEarlier}, - * then the classes in {@code rt.jar} are compiled. Otherwise the classes in {@code - * /lib/modules} are compiled. + * Magic token to denote that JDK classes are to be compiled. If + * {@link JDK9Method#Java8OrEarlier}, then the classes in {@code rt.jar} are compiled. Otherwise + * the classes in the Java runtime image are compiled. */ public static final String SUN_BOOT_CLASS_PATH = "sun.boot.class.path"; /** - * A mechanism for overriding JVMCI options that affect compilation. A {@link Config} object - * should be used in a try-with-resources statement to ensure overriding of options is scoped - * properly. For example: - * - *

      -     *     Config config = ...;
      -     *     try (AutoCloseable s = config == null ? null : config.apply()) {
      -     *         // perform a JVMCI compilation
      -     *     }
      -     * 
      + * Magic token to denote the classes in the Java runtime image (i.e. in the {@code jrt:/} file + * system). */ - @SuppressWarnings("serial") - public static class Config extends HashMap, Object> implements OptionConsumer { - /** - * Creates a {@link Config} object by parsing a set of space separated override options. - * - * @param options a space separated set of option value settings with each option setting in - * a {@code -Dgraal.=} format but without the leading - * {@code -Dgraal.}. Ignored if null. - */ - public Config(String options) { - if (options != null) { - Map optionSettings = new HashMap<>(); - for (String optionSetting : options.split("\\s+|#")) { - OptionsParser.parseOptionSettingTo(optionSetting, optionSettings); - } - OptionsParser.parseOptions(optionSettings, this, ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader())); + public static final String JRT_CLASS_PATH_ENTRY = ""; + + /** + * @param options a space separated set of option value settings with each option setting in a + * {@code -Dgraal.=} format but without the leading {@code -Dgraal.}. + * Ignored if null. + */ + public static EconomicMap, Object> parseOptions(String options) { + if (options != null) { + EconomicMap optionSettings = EconomicMap.create(); + for (String optionSetting : options.split("\\s+|#")) { + OptionsParser.parseOptionSettingTo(optionSetting, optionSettings); } + EconomicMap, Object> values = OptionValues.newOptionMap(); + ServiceLoader loader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader()); + OptionsParser.parseOptions(optionSettings, values, loader); + return values; } - - /** - * Applies the overrides represented by this object. The overrides are in effect until - * {@link OverrideScope#close()} is called on the returned object. - */ - OverrideScope apply() { - return OptionValue.override(this); - } - - @Override - public void set(OptionDescriptor desc, Object value) { - put(desc.getOptionValue(), value); - } + return EconomicMap.create(); } private final HotSpotJVMCIRuntimeProvider jvmciRuntime; @@ -167,21 +142,21 @@ public final class CompileTheWorld { /** * Class path denoting classes to compile. * - * @see CompileTheWorldOptions#CompileTheWorldClasspath + * @see Options#Classpath */ private final String inputClassPath; /** * Class index to start compilation at. * - * @see CompileTheWorldOptions#CompileTheWorldStartAt + * @see Options#StartAt */ private final int startAt; /** * Class index to stop compilation at. * - * @see CompileTheWorldOptions#CompileTheWorldStopAt + * @see Options#StopAt */ private final int stopAt; @@ -198,7 +173,6 @@ public final class CompileTheWorld { private AtomicLong memoryUsed = new AtomicLong(); private boolean verbose; - private final Config config; /** * Signal that the threads should start compiling in multithreaded mode. @@ -207,6 +181,9 @@ public final class CompileTheWorld { private ThreadPoolExecutor threadPool; + private OptionValues currentOptions; + private final UnmodifiableEconomicMap, Object> compilationOptions; + /** * Creates a compile-the-world instance. * @@ -216,8 +193,8 @@ public final class CompileTheWorld { * @param methodFilters * @param excludeMethodFilters */ - public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, String files, Config config, int startAt, int stopAt, String methodFilters, - String excludeMethodFilters, boolean verbose) { + public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, String files, int startAt, int stopAt, String methodFilters, String excludeMethodFilters, + boolean verbose, OptionValues initialOptions, EconomicMap, Object> compilationOptions) { this.jvmciRuntime = jvmciRuntime; this.compiler = compiler; this.inputClassPath = files; @@ -226,30 +203,37 @@ public final class CompileTheWorld { this.methodFilters = methodFilters == null || methodFilters.isEmpty() ? null : MethodFilter.parse(methodFilters); this.excludeMethodFilters = excludeMethodFilters == null || excludeMethodFilters.isEmpty() ? null : MethodFilter.parse(excludeMethodFilters); this.verbose = verbose; - this.config = config; + this.currentOptions = initialOptions; - // We don't want the VM to exit when a method fails to compile... - config.putIfAbsent(ExitVMOnException, false); + // Copy the initial options and add in any extra options + EconomicMap, Object> compilationOptionsCopy = EconomicMap.create(initialOptions.getMap()); + compilationOptionsCopy.putAll(compilationOptions); - // ...but we want to see exceptions. - config.putIfAbsent(PrintBailout, true); - config.putIfAbsent(PrintStackTraceOnException, true); + // We want to see stack traces when a method fails to compile + CompilationBailoutAction.putIfAbsent(compilationOptionsCopy, Print); + CompilationFailureAction.putIfAbsent(compilationOptionsCopy, Print); + + // By default only report statistics for the CTW threads themselves + DebugOptions.MetricsThreadFilter.putIfAbsent(compilationOptionsCopy, "^CompileTheWorld"); + this.compilationOptions = compilationOptionsCopy; } - public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler) { - this(jvmciRuntime, compiler, CompileTheWorldClasspath.getValue(), new Config(CompileTheWorldConfig.getValue()), CompileTheWorldStartAt.getValue(), CompileTheWorldStopAt.getValue(), - CompileTheWorldMethodFilter.getValue(), CompileTheWorldExcludeMethodFilter.getValue(), CompileTheWorldVerbose.getValue()); + public CompileTheWorld(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, OptionValues options) { + this(jvmciRuntime, compiler, Options.Classpath.getValue(options), + Options.StartAt.getValue(options), + Options.StopAt.getValue(options), + Options.MethodFilter.getValue(options), + Options.ExcludeMethodFilter.getValue(options), + Options.Verbose.getValue(options), + options, + parseOptions(Options.Config.getValue(options))); } /** * Compiles all methods in all classes in {@link #inputClassPath}. If {@link #inputClassPath} - * equals {@link #SUN_BOOT_CLASS_PATH} the boot class path is used. + * equals {@link #SUN_BOOT_CLASS_PATH} the boot classes are used. */ public void compile() throws Throwable { - // By default only report statistics for the CTW threads themselves - if (!GraalDebugConfig.Options.DebugValueThreadFilter.hasBeenSet()) { - GraalDebugConfig.Options.DebugValueThreadFilter.setValue("^CompileTheWorld"); - } if (SUN_BOOT_CLASS_PATH.equals(inputClassPath)) { String bcpEntry = null; if (Java8OrEarlier) { @@ -257,13 +241,15 @@ public final class CompileTheWorld { for (int i = 0; i < entries.length && bcpEntry == null; i++) { String entry = entries[i]; File entryFile = new File(entry); - // We stop at rt.jar, unless it is the first boot class path entry. if (entryFile.getName().endsWith("rt.jar") && entryFile.isFile()) { bcpEntry = entry; } } + if (bcpEntry == null) { + throw new GraalError("Could not find rt.jar on boot class path %s", System.getProperty(SUN_BOOT_CLASS_PATH)); + } } else { - bcpEntry = System.getProperty("java.home") + "/lib/modules".replace('/', File.separatorChar); + bcpEntry = JRT_CLASS_PATH_ENTRY; } compile(bcpEntry); } else { @@ -413,92 +399,70 @@ public final class CompileTheWorld { } /** - * Name of the property that limits the set of modules processed by CompileTheWorld. + * A class path entry representing the {@code jrt:/} file system. */ - public static final String LIMITMODS_PROPERTY_NAME = "CompileTheWorld.limitmods"; + static class JRTClassPathEntry extends ClassPathEntry { - /** - * A class path entry that is a jimage file. - */ - static class ImageClassPathEntry extends ClassPathEntry { + private final String limitModules; - private final File jimage; - - ImageClassPathEntry(String name) { + JRTClassPathEntry(String name, String limitModules) { super(name); - jimage = new File(name); - assert jimage.isFile(); + this.limitModules = limitModules; } @Override public ClassLoader createClassLoader() throws IOException { - URL url = jimage.toURI().toURL(); + URL url = URI.create("jrt:/").toURL(); return new URLClassLoader(new URL[]{url}); } @Override public List getClassNames() throws IOException { - String prop = System.getProperty(LIMITMODS_PROPERTY_NAME); - Set limitmods = prop == null ? null : new HashSet<>(Arrays.asList(prop.split(","))); - List classNames = new ArrayList<>(); - String[] entries = readJimageEntries(); - for (String e : entries) { - if (e.endsWith(".class") && !e.endsWith("module-info.class")) { - assert e.charAt(0) == '/' : e; - int endModule = e.indexOf('/', 1); - assert endModule != -1 : e; - if (limitmods != null) { - String module = e.substring(1, endModule); - if (!limitmods.contains(module)) { - continue; - } + Set negative = new HashSet<>(); + Set positive = new HashSet<>(); + if (limitModules != null && !limitModules.isEmpty()) { + for (String s : limitModules.split(",")) { + if (s.startsWith("~")) { + negative.add(s.substring(1)); + } else { + positive.add(s); } - // Strip the module prefix and convert to dotted form - String className = e.substring(endModule + 1).replace('/', '.'); - // Strip ".class" suffix - className = className.replace('/', '.').substring(0, className.length() - ".class".length()); - classNames.add(className); } } + List classNames = new ArrayList<>(); + FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), Collections.emptyMap()); + Path top = fs.getPath("/modules/"); + Files.find(top, Integer.MAX_VALUE, + (path, attrs) -> attrs.isRegularFile()).forEach(p -> { + int nameCount = p.getNameCount(); + if (nameCount > 2) { + String base = p.getName(nameCount - 1).toString(); + if (base.endsWith(".class") && !base.equals("module-info.class")) { + String module = p.getName(1).toString(); + if (positive.isEmpty() || positive.contains(module)) { + if (negative.isEmpty() || !negative.contains(module)) { + // Strip module prefix and convert to dotted form + String className = p.subpath(2, nameCount).toString().replace('/', '.'); + // Strip ".class" suffix + className = className.replace('/', '.').substring(0, className.length() - ".class".length()); + classNames.add(className); + } + } + } + } + }); return classNames; } - - private String[] readJimageEntries() { - try { - // Use reflection so this can be compiled on JDK8 - Path path = FileSystems.getDefault().getPath(name); - Method open = Class.forName("jdk.internal.jimage.BasicImageReader").getDeclaredMethod("open", Path.class); - Object reader = open.invoke(null, path); - Method getEntryNames = reader.getClass().getDeclaredMethod("getEntryNames"); - getEntryNames.setAccessible(true); - String[] entries = (String[]) getEntryNames.invoke(reader); - return entries; - } catch (Exception e) { - TTY.println("Error reading entries from " + name + ": " + e); - return new String[0]; - } - } } - /** - * Determines if a given path denotes a jimage file. - * - * @param path file path - * @return {@code true} if the 4 byte integer (in native endianness) at the start of - * {@code path}'s contents is {@code 0xCAFEDADA} - */ - static boolean isJImage(String path) { - try { - FileChannel channel = FileChannel.open(Paths.get(path), StandardOpenOption.READ); - ByteBuffer map = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); - map.order(ByteOrder.nativeOrder()).asIntBuffer().get(0); - int magic = map.asIntBuffer().get(0); - if (magic == 0xCAFEDADA) { - return true; - } - } catch (IOException e) { + private boolean isClassIncluded(String className) { + if (methodFilters != null && !MethodFilter.matchesClassName(methodFilters, className)) { + return false; } - return false; + if (excludeMethodFilters != null && MethodFilter.matchesClassName(excludeMethodFilters, className)) { + return false; + } + return true; } /** @@ -512,16 +476,6 @@ public final class CompileTheWorld { final String[] entries = classPath.split(File.pathSeparator); long start = System.currentTimeMillis(); - CompilerThreadFactory factory = new CompilerThreadFactory("CompileTheWorld", new DebugConfigAccess() { - @Override - public GraalDebugConfig getDebugConfig() { - if (Debug.isEnabled() && DebugScope.getConfig() == null) { - return DebugEnvironment.initialize(System.out, compiler.getGraalRuntime().getHostProviders().getSnippetReflection()); - } - return null; - } - }); - try { // compile dummy method to get compiler initialized outside of the // config debug override. @@ -530,7 +484,7 @@ public final class CompileTheWorld { int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; boolean useProfilingInfo = false; boolean installAsDefault = false; - CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault); + CompilationTask task = new CompilationTask(jvmciRuntime, compiler, new HotSpotCompilationRequest(dummyMethod, entryBCI, 0L), useProfilingInfo, installAsDefault, currentOptions); task.runCompilation(); } catch (NoSuchMethodException | SecurityException e1) { printStackTrace(e1); @@ -541,26 +495,28 @@ public final class CompileTheWorld { * DebugValueThreadFilter to filter on the thread names. */ int threadCount = 1; - if (CompileTheWorldOptions.CompileTheWorldMultiThreaded.getValue()) { - threadCount = CompileTheWorldOptions.CompileTheWorldThreads.getValue(); + if (Options.MultiThreaded.getValue(currentOptions)) { + threadCount = Options.Threads.getValue(currentOptions); if (threadCount == 0) { threadCount = Runtime.getRuntime().availableProcessors(); } } else { running = true; } - threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); - try (OverrideScope s = config.apply()) { + OptionValues savedOptions = currentOptions; + currentOptions = new OptionValues(compilationOptions); + threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new CompilerThreadFactory("CompileTheWorld")); + + try { for (int i = 0; i < entries.length; i++) { final String entry = entries[i]; ClassPathEntry cpe; if (entry.endsWith(".zip") || entry.endsWith(".jar")) { cpe = new JarClassPathEntry(entry); - } else if (isJImage(entry)) { - assert !Java8OrEarlier; - cpe = new ImageClassPathEntry(entry); + } else if (entry.equals(JRT_CLASS_PATH_ENTRY)) { + cpe = new JRTClassPathEntry(entry, Options.LimitModules.getValue(currentOptions)); } else { if (!new File(entry).isDirectory()) { println("CompileTheWorld : Skipped classes in " + entry); @@ -610,17 +566,17 @@ public final class CompileTheWorld { } } catch (Throwable t) { // If something went wrong during pre-loading we just ignore it. - println("Preloading failed for (%d) %s: %s", classFileCounter, className, t); + if (isClassIncluded(className)) { + println("Preloading failed for (%d) %s: %s", classFileCounter, className, t); + } + continue; } /* * Only check filters after class loading and resolution to mitigate impact * on reproducibility. */ - if (methodFilters != null && !MethodFilter.matchesClassName(methodFilters, className)) { - continue; - } - if (excludeMethodFilters != null && MethodFilter.matchesClassName(excludeMethodFilters, className)) { + if (!isClassIncluded(className)) { continue; } @@ -650,12 +606,16 @@ public final class CompileTheWorld { } } } catch (Throwable t) { - println("CompileTheWorld (%d) : Skipping %s %s", classFileCounter, className, t.toString()); - printStackTrace(t); + if (isClassIncluded(className)) { + println("CompileTheWorld (%d) : Skipping %s %s", classFileCounter, className, t.toString()); + printStackTrace(t); + } } } cpe.close(); } + } finally { + currentOptions = savedOptions; } if (!running) { @@ -677,7 +637,7 @@ public final class CompileTheWorld { long elapsedTime = System.currentTimeMillis() - start; println(); - if (CompileTheWorldOptions.CompileTheWorldMultiThreaded.getValue()) { + if (Options.MultiThreaded.getValue(currentOptions)) { TTY.println("CompileTheWorld : Done (%d classes, %d methods, %d ms elapsed, %d ms compile time, %d bytes of memory used)", classFileCounter, compiledMethodsCounter.get(), elapsedTime, compileTime.get(), memoryUsed.get()); } else { @@ -712,8 +672,12 @@ public final class CompileTheWorld { @Override public void run() { waitToRun(); - try (OverrideScope s = config.apply()) { + OptionValues savedOptions = currentOptions; + currentOptions = new OptionValues(compilationOptions); + try { compileMethod(method, classFileCounter); + } finally { + currentOptions = savedOptions; } } }); @@ -728,13 +692,13 @@ public final class CompileTheWorld { private void compileMethod(HotSpotResolvedJavaMethod method, int counter) { try { long start = System.currentTimeMillis(); - long allocatedAtStart = MemUseTrackerImpl.getCurrentThreadAllocatedBytes(); + long allocatedAtStart = getCurrentThreadAllocatedBytes(); int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, 0L); // For more stable CTW execution, disable use of profiling information boolean useProfilingInfo = false; boolean installAsDefault = false; - CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault); + CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, useProfilingInfo, installAsDefault, currentOptions); task.runCompilation(); // Invalidate the generated code so the code cache doesn't fill up @@ -743,7 +707,7 @@ public final class CompileTheWorld { installedCode.invalidate(); } - memoryUsed.getAndAdd(MemUseTrackerImpl.getCurrentThreadAllocatedBytes() - allocatedAtStart); + memoryUsed.getAndAdd(getCurrentThreadAllocatedBytes() - allocatedAtStart); compileTime.getAndAdd(System.currentTimeMillis() - start); compiledMethodsCounter.incrementAndGet(); } catch (Throwable t) { @@ -783,8 +747,72 @@ public final class CompileTheWorld { return true; } + static class Options { + // @formatter:off + public static final OptionKey Help = new OptionKey<>(false); + public static final OptionKey Classpath = new OptionKey<>(CompileTheWorld.SUN_BOOT_CLASS_PATH); + public static final OptionKey Verbose = new OptionKey<>(true); + /** + * Ignore Graal classes by default to avoid problems associated with compiling + * snippets and method substitutions. + */ + public static final OptionKey LimitModules = new OptionKey<>("~jdk.internal.vm.compiler"); + public static final OptionKey Iterations = new OptionKey<>(1); + public static final OptionKey MethodFilter = new OptionKey<>(null); + public static final OptionKey ExcludeMethodFilter = new OptionKey<>(null); + public static final OptionKey StartAt = new OptionKey<>(1); + public static final OptionKey StopAt = new OptionKey<>(Integer.MAX_VALUE); + public static final OptionKey Config = new OptionKey<>(null); + public static final OptionKey MultiThreaded = new OptionKey<>(false); + public static final OptionKey Threads = new OptionKey<>(0); + + static final ReflectionOptionDescriptors DESCRIPTORS = new ReflectionOptionDescriptors(Options.class, + "Help", "List options and their help messages and then exit.", + "Classpath", "Class path denoting methods to compile. Default is to compile boot classes.", + "Verbose", "Verbose operation.", + "LimitModules", "Comma separated list of module names to which compilation should be limited. " + + "Module names can be prefixed with \"~\" to exclude the named module.", + "Iterations", "The number of iterations to perform.", + "MethodFilter", "Only compile methods matching this filter.", + "ExcludeMethodFilter", "Exclude methods matching this filter from compilation.", + "StartAt", "First class to consider for compilation.", + "StopAt", "Last class to consider for compilation.", + "Config", "Option value overrides to use during compile the world. For example, " + + "to disable inlining and partial escape analysis specify 'PartialEscapeAnalysis=false Inline=false'. " + + "The format for each option is the same as on the command line just without the '-Dgraal.' prefix.", + "MultiThreaded", "Run using multiple threads for compilation.", + "Threads", "Number of threads to use for multithreaded execution. Defaults to Runtime.getRuntime().availableProcessors()."); + // @formatter:on + } + + public static OptionValues loadOptions(OptionValues initialValues) { + EconomicMap, Object> values = OptionValues.newOptionMap(); + List loader = singletonList(DESCRIPTORS); + OptionsParser.parseOptions(extractEntries(System.getProperties(), "CompileTheWorld.", true), values, loader); + OptionValues options = new OptionValues(initialValues, values); + if (Options.Help.getValue(options)) { + options.printHelp(loader, System.out, "CompileTheWorld."); + System.exit(0); + } + return options; + } + public static void main(String[] args) throws Throwable { - HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) HotSpotJVMCIRuntime.runtime().getCompiler(); - compiler.compileTheWorld(); + HotSpotJVMCIRuntime jvmciRuntime = HotSpotJVMCIRuntime.runtime(); + HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) jvmciRuntime.getCompiler(); + HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime(); + HotSpotCodeCacheProvider codeCache = graalRuntime.getHostProviders().getCodeCache(); + OptionValues options = loadOptions(graalRuntime.getOptions()); + + int iterations = Options.Iterations.getValue(options); + for (int i = 0; i < iterations; i++) { + codeCache.resetCompilationStatistics(); + TTY.println("CompileTheWorld : iteration " + i); + + CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, compiler, options); + ctw.compile(); + } + // This is required as non-daemon threads can be started by class initializers + System.exit(0); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java index 481a3387af5..3982a11f925 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java @@ -22,14 +22,16 @@ */ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException; - -import org.junit.Test; +import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction; +import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction; +import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction; import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.hotspot.CompileTheWorld; -import org.graalvm.compiler.hotspot.CompileTheWorld.Config; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.junit.Test; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; @@ -41,11 +43,15 @@ public class CompileTheWorldTest extends GraalCompilerTest { @Test public void testJDK() throws Throwable { - boolean originalSetting = ExitVMOnException.getValue(); + ExceptionAction originalBailoutAction = CompilationBailoutAction.getValue(getInitialOptions()); + ExceptionAction originalFailureAction = CompilationFailureAction.getValue(getInitialOptions()); // Compile a couple classes in rt.jar HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); - System.setProperty(CompileTheWorld.LIMITMODS_PROPERTY_NAME, "java.base"); - new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, new Config("Inline=false"), 1, 5, null, null, true).compile(); - assert ExitVMOnException.getValue() == originalSetting; + System.setProperty("CompileTheWorld.LimitModules", "java.base"); + OptionValues initialOptions = getInitialOptions(); + EconomicMap, Object> compilationOptions = CompileTheWorld.parseOptions("Inline=false"); + new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, false, initialOptions, compilationOptions).compile(); + assert CompilationBailoutAction.getValue(initialOptions) == originalBailoutAction; + assert CompilationFailureAction.getValue(initialOptions) == originalFailureAction; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java index 3edc637a362..f11ef51bad1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ConstantPoolSubstitutionsTests.java @@ -23,40 +23,43 @@ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.core.common.util.ModuleAPI.addExports; -import static org.graalvm.compiler.core.common.util.ModuleAPI.getModule; +import static org.graalvm.compiler.test.JLModule.uncheckedAddExports; import java.lang.reflect.Method; -import org.graalvm.compiler.core.common.util.Util; import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.test.JLModule; import org.junit.BeforeClass; import org.junit.Test; - import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; + import jdk.vm.ci.meta.ResolvedJavaMethod; -public class ConstantPoolSubstitutionsTests extends GraalCompilerTest implements Opcodes { +public class ConstantPoolSubstitutionsTests extends GraalCompilerTest { + + public ConstantPoolSubstitutionsTests() { + exportPackage(JAVA_BASE, "jdk.internal.org.objectweb.asm"); + } @SuppressWarnings("try") protected StructuredGraph test(final String snippet) { ResolvedJavaMethod method = getMetaAccess().lookupJavaMethod(getMethod(snippet)); - try (Scope s = Debug.scope("ConstantPoolSubstitutionsTests", method)) { + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("ConstantPoolSubstitutionsTests", method)) { StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); compile(graph.method(), graph); assertNotInGraph(graph, Invoke.class); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet); + debug.dump(DebugContext.BASIC_LEVEL, graph, snippet); return graph; } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } @@ -105,67 +108,40 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest implements * This test uses some API hidden by the JDK9 module system. */ private static void addExports(Class c) { - if (!Util.Java8OrEarlier) { - Object javaBaseModule = getModule.invoke(String.class); - Object cModule = getModule.invoke(c); - addExports.invokeStatic(javaBaseModule, "jdk.internal.reflect", cModule); - addExports.invokeStatic(javaBaseModule, "jdk.internal.misc", cModule); + if (!Java8OrEarlier) { + Object javaBaseModule = JLModule.fromClass(String.class); + Object cModule = JLModule.fromClass(c); + uncheckedAddExports(javaBaseModule, "jdk.internal.reflect", cModule); + uncheckedAddExports(javaBaseModule, "jdk.internal.misc", cModule); } } - /** - * Disables these tests until we know how to dynamically export the {@code jdk.internal.reflect} - * package from the {@code java.base} module to the unnamed module associated with - * {@link AsmLoader}. Without such an export, the test fails as follows: - * - *
      -     * Caused by: java.lang.IllegalAccessError: class org.graalvm.compiler.hotspot.test.ConstantPoolTest
      -     * (in unnamed module @0x57599b23) cannot access class jdk.internal.reflect.ConstantPool (in
      -     * module java.base) because module java.base does not export jdk.internal.reflect to unnamed
      -     * module @0x57599b23
      -     * 
      - */ - private static void assumeJDK8() { - // Assume.assumeTrue(Java8OrEarlier); - } - @Test public void testGetSize() { - assumeJDK8(); Object cp = getConstantPoolForObject(); test("getSize", cp); } @Test public void testGetIntAt() { - assumeJDK8(); test("getIntAt"); } @Test public void testGetLongAt() { - assumeJDK8(); test("getLongAt"); } @Test public void testGetFloatAt() { - assumeJDK8(); test("getFloatAt"); } @Test public void testGetDoubleAt() { - assumeJDK8(); test("getDoubleAt"); } - // @Test - public void testGetUTF8At() { - assumeJDK8(); - test("getUTF8At"); - } - private static final String PACKAGE_NAME = ConstantPoolSubstitutionsTests.class.getPackage().getName(); private static final String PACKAGE_NAME_INTERNAL = PACKAGE_NAME.replace('.', '/'); @@ -186,7 +162,7 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest implements if (loaded != null) { return loaded; } - byte[] bytes = generateClass(); + byte[] bytes = Gen.generateClass(); return (loaded = defineClass(name, bytes, 0, bytes.length)); } else { return super.findClass(name); @@ -194,131 +170,134 @@ public class ConstantPoolSubstitutionsTests extends GraalCompilerTest implements } } - // @formatter:off - /* - static class ConstantPoolTest { - public static int getSize(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getSize(); + static class Gen implements Opcodes { + // @formatter:off + /* + static class ConstantPoolTest { + public static int getSize(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getSize(); + } + + public static int getIntAt(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getIntAt(0); + } + + public static long getLongAt(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getLongAt(0); + } + + public static float getFloatAt(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getFloatAt(0); + } + + public static double getDoubleAt(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getDoubleAt(0); + } + + public static String getUTF8At(Object o) { + ConstantPool cp = (ConstantPool) o; + return cp.getUTF8At(0); + } } + */ + // @formatter:on - public static int getIntAt(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getIntAt(0); + static byte[] generateClass() { + + ClassWriter cw = new ClassWriter(0); + MethodVisitor mv; + + cw.visit(52, ACC_SUPER, PACKAGE_NAME_INTERNAL + "/ConstantPoolTest", null, "java/lang/Object", null); + cw.visitInnerClass(PACKAGE_NAME_INTERNAL + "/ConstantPoolTest", PACKAGE_NAME_INTERNAL + "/ConstantPoolSubstitutionsTests", "ConstantPoolTest", + ACC_STATIC); + String constantPool = Java8OrEarlier ? "sun/reflect/ConstantPool" : "jdk/internal/reflect/ConstantPool"; + + mv = cw.visitMethod(0, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getSize", "(Ljava/lang/Object;)I", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getSize", "()I", false); + mv.visitInsn(IRETURN); + mv.visitMaxs(1, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getIntAt", "(Ljava/lang/Object;)I", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getIntAt", "(I)I", false); + mv.visitInsn(IRETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getLongAt", "(Ljava/lang/Object;)J", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getLongAt", "(I)J", false); + mv.visitInsn(LRETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getFloatAt", "(Ljava/lang/Object;)F", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getFloatAt", "(I)F", false); + mv.visitInsn(FRETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getDoubleAt", "(Ljava/lang/Object;)D", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getDoubleAt", "(I)D", false); + mv.visitInsn(DRETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + + mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getUTF8At", "(Ljava/lang/Object;)Ljava/lang/String;", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitTypeInsn(CHECKCAST, constantPool); + mv.visitVarInsn(ASTORE, 1); + mv.visitVarInsn(ALOAD, 1); + mv.visitInsn(ICONST_0); + mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getUTF8At", "(I)Ljava/lang/String;", false); + mv.visitInsn(ARETURN); + mv.visitMaxs(2, 3); + mv.visitEnd(); + cw.visitEnd(); + + return cw.toByteArray(); } - - public static long getLongAt(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getLongAt(0); - } - - public static float getFloatAt(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getFloatAt(0); - } - - public static double getDoubleAt(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getDoubleAt(0); - } - - public static String getUTF8At(Object o) { - ConstantPool cp = (ConstantPool) o; - return cp.getUTF8At(0); - } - } - */ - // @formatter:on - private static byte[] generateClass() { - - ClassWriter cw = new ClassWriter(0); - MethodVisitor mv; - - cw.visit(52, ACC_SUPER, PACKAGE_NAME_INTERNAL + "/ConstantPoolTest", null, "java/lang/Object", null); - cw.visitInnerClass(PACKAGE_NAME_INTERNAL + "/ConstantPoolTest", PACKAGE_NAME_INTERNAL + "/ConstantPoolSubstitutionsTests", "ConstantPoolTest", - ACC_STATIC); - String constantPool = Java8OrEarlier ? "sun/reflect/ConstantPool" : "jdk/internal/reflect/ConstantPool"; - - mv = cw.visitMethod(0, "", "()V", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); - mv.visitInsn(RETURN); - mv.visitMaxs(1, 1); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getSize", "(Ljava/lang/Object;)I", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getSize", "()I", false); - mv.visitInsn(IRETURN); - mv.visitMaxs(1, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getIntAt", "(Ljava/lang/Object;)I", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getIntAt", "(I)I", false); - mv.visitInsn(IRETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getLongAt", "(Ljava/lang/Object;)J", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getLongAt", "(I)J", false); - mv.visitInsn(LRETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getFloatAt", "(Ljava/lang/Object;)F", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getFloatAt", "(I)F", false); - mv.visitInsn(FRETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getDoubleAt", "(Ljava/lang/Object;)D", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getDoubleAt", "(I)D", false); - mv.visitInsn(DRETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "getUTF8At", "(Ljava/lang/Object;)Ljava/lang/String;", null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitTypeInsn(CHECKCAST, constantPool); - mv.visitVarInsn(ASTORE, 1); - mv.visitVarInsn(ALOAD, 1); - mv.visitInsn(ICONST_0); - mv.visitMethodInsn(INVOKEVIRTUAL, constantPool, "getUTF8At", "(I)Ljava/lang/String;", false); - mv.visitInsn(ARETURN); - mv.visitMaxs(2, 3); - mv.visitEnd(); - cw.visitEnd(); - - return cw.toByteArray(); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DataPatchTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DataPatchTest.java index 445c48e2482..32675cc157c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DataPatchTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/DataPatchTest.java @@ -23,18 +23,16 @@ package org.graalvm.compiler.hotspot.test; -import org.junit.Assume; -import org.junit.Test; - -import org.graalvm.compiler.hotspot.CompressEncoding; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; +import org.graalvm.compiler.core.common.CompressEncoding; +import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.debug.OpaqueNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration; +import org.junit.Assume; +import org.junit.Test; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -74,19 +72,18 @@ public class DataPatchTest extends HotSpotGraalCompilerTest { } @Override - protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) { - InvocationPlugins invocationPlugins = conf.getPlugins().getInvocationPlugins(); + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { Registration r = new Registration(invocationPlugins, DataPatchTest.class); r.register1("compressUncompress", Object.class, new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { CompressEncoding encoding = runtime().getVMConfig().getOopEncoding(); - ValueNode compressed = b.add(CompressionNode.compress(arg, encoding)); + ValueNode compressed = b.add(HotSpotCompressionNode.compress(arg, encoding)); ValueNode proxy = b.add(new OpaqueNode(compressed)); - b.addPush(JavaKind.Object, CompressionNode.uncompress(proxy, encoding)); + b.addPush(JavaKind.Object, HotSpotCompressionNode.uncompress(proxy, encoding)); return true; } }); - return super.editGraphBuilderConfiguration(conf); + super.registerInvocationPlugins(invocationPlugins); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/EliminateRedundantInitializationPhaseTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/EliminateRedundantInitializationPhaseTest.java new file mode 100644 index 00000000000..97b8543cd2b --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/EliminateRedundantInitializationPhaseTest.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.test; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin; +import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; +import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Assert; +import org.junit.Test; + +public class EliminateRedundantInitializationPhaseTest extends GraalCompilerTest { + @Override + protected Plugins getDefaultGraphBuilderPlugins() { + Plugins plugins = super.getDefaultGraphBuilderPlugins(); + plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin()); + return plugins; + } + + public static class X { + public static int x; + public static int y; + public static int z; + } + + public static class Y extends X { + public static int a; + public static int b; + } + + public static void assignFields() { + X.x = 1; + X.y = 2; + X.z = 3; + } + + public static void assignFieldsConditionally(boolean choice) { + X.x = 1; + if (choice) { + X.y = 2; + } else { + X.z = 3; + } + } + + public static void assignFieldsSubclassDominates() { + Y.a = 1; + X.x = 2; + X.y = 3; + X.z = 4; + } + + public static void assignFieldsConditionallySubclassDominates(boolean choice) { + Y.a = 1; + if (choice) { + X.x = 2; + } else { + X.y = 3; + } + Y.z = 4; + } + + public static void assignFieldsSubclassPostdominates() { + X.x = 1; + Y.a = 2; + } + + public static void assignFieldsConditionallySubclassPostdominates(boolean choice) { + X.x = 1; + if (choice) { + X.y = 2; + } else { + X.z = 3; + } + Y.a = 4; + } + + public static void assignFieldsConditionallyMixed(boolean choice) { + X.x = 1; + if (choice) { + Y.a = 2; + } else { + X.z = 3; + } + Y.b = 4; + } + + public static void assignFieldsInLoop() { + X.x = 1; + for (int i = 0; i < 10; i++) { + X.y += X.z; + } + } + + public static void assignFieldsInBranches(boolean choice) { + if (choice) { + X.x = 1; + } else { + X.y = 2; + } + X.z = 3; + } + + public static void assignFieldsInBranchesMixed(boolean choice) { + if (choice) { + X.x = 1; + } else { + Y.a = 2; + } + X.z = 3; + } + + private void test(String name, int initNodesAfterParse, int initNodesAfterOpt) { + StructuredGraph graph = parseEager(name, AllowAssumptions.NO); + Assert.assertEquals(initNodesAfterParse, graph.getNodes().filter(InitializeKlassNode.class).count()); + HighTierContext highTierContext = getDefaultHighTierContext(); + new EliminateRedundantInitializationPhase().apply(graph, highTierContext); + Assert.assertEquals(initNodesAfterOpt, graph.getNodes().filter(InitializeKlassNode.class).count()); + } + + @Test + public void test1() { + test("assignFields", 3, 1); + } + + @Test + public void test2() { + test("assignFieldsConditionally", 3, 1); + } + + @Test + public void test3() { + test("assignFieldsSubclassDominates", 4, 1); + } + + @Test + public void test4() { + test("assignFieldsConditionallySubclassDominates", 4, 1); + } + + @Test + public void test5() { + test("assignFieldsSubclassPostdominates", 2, 2); + } + + @Test + public void test6() { + test("assignFieldsConditionallySubclassPostdominates", 4, 2); + } + + @Test + public void test7() { + test("assignFieldsConditionallyMixed", 4, 3); + } + + @Test + public void test8() { + test("assignFieldsInLoop", 4, 1); + } + + @Test + public void test9() { + test("assignFieldsInBranches", 3, 2); + } + + @Test + public void test10() { + test("assignFieldsInBranchesMixed", 3, 2); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ExplicitExceptionTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ExplicitExceptionTest.java index b1099a426e7..44dbfe55e67 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ExplicitExceptionTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ExplicitExceptionTest.java @@ -25,7 +25,9 @@ package org.graalvm.compiler.hotspot.test; import org.junit.Test; import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -35,8 +37,8 @@ public class ExplicitExceptionTest extends GraalCompilerTest { private int expectedForeignCallCount; @Override - protected InstalledCode getCode(ResolvedJavaMethod method) { - InstalledCode installedCode = super.getCode(method); + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { + InstalledCode installedCode = super.getCode(method, graph, forceCompile, installAsDefault, options); assertDeepEquals(expectedForeignCallCount, lastCompiledGraph.getNodes().filter(ForeignCallNode.class).count()); return installedCode; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ForeignCallDeoptimizeTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ForeignCallDeoptimizeTest.java index 12c411f12a4..a623d56d927 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ForeignCallDeoptimizeTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ForeignCallDeoptimizeTest.java @@ -30,9 +30,9 @@ import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; +import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -43,11 +43,9 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class ForeignCallDeoptimizeTest extends GraalCompilerTest { @Override - protected Plugins getDefaultGraphBuilderPlugins() { + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { ForeignCallsProvider foreignCalls = ((HotSpotProviders) getProviders()).getForeignCalls(); - - Plugins ret = super.getDefaultGraphBuilderPlugins(); - ret.getInvocationPlugins().register(new InvocationPlugin() { + invocationPlugins.register(new InvocationPlugin() { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { @@ -56,7 +54,7 @@ public class ForeignCallDeoptimizeTest extends GraalCompilerTest { return true; } }, ForeignCallDeoptimizeTest.class, "testCallInt", int.class); - return ret; + super.registerInvocationPlugins(invocationPlugins); } public static int testCallInt(int value) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java index 5466a638e79..bff37edeb79 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java @@ -22,35 +22,657 @@ */ package org.graalvm.compiler.hotspot.test; -import org.junit.Ignore; -import org.junit.Test; +import java.lang.management.ManagementFactory; +import java.lang.management.MonitorInfo; +import java.lang.management.ThreadInfo; +import java.lang.management.ThreadMXBean; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; import org.graalvm.compiler.api.directives.GraalDirectives; +import org.graalvm.compiler.core.phases.HighTier; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.TTY; +import org.graalvm.compiler.hotspot.phases.OnStackReplacementPhase; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.junit.Assert; +import org.junit.Test; + +import jdk.vm.ci.meta.ResolvedJavaMethod; +import org.junit.Assume; /** * Test on-stack-replacement with locks. */ public class GraalOSRLockTest extends GraalOSRTestBase { - @Ignore("OSR with locks not supported") - @Test - public void testOSR() { - testOSR("test"); + private static boolean TestInSeparateThread = false; + + public GraalOSRLockTest() { + try { + Class.forName("java.lang.management.ManagementFactory"); + } catch (ClassNotFoundException ex) { + Assume.assumeNoException("cannot check for monitors without java.management JDK9 module", ex); + } } - static int limit = 10000; + // testing only + public static boolean isMonitorLockHeld(Object o) { + return isMonitorLockHeldByThread(o, null); + } - private static Object lock = new Object(); + public static boolean isMonitorLockHeldByThread(Object o, Thread t) { + int oihc = System.identityHashCode(o); + ThreadMXBean tmxbean = ManagementFactory.getThreadMXBean(); + ThreadInfo[] tinfos = tmxbean.dumpAllThreads(true, false); - public static ReturnValue test() { - synchronized (lock) { - for (int i = 0; i < limit * limit; i++) { - GraalDirectives.blackhole(i); - if (GraalDirectives.inCompiledCode()) { - return ReturnValue.SUCCESS; + for (ThreadInfo ti : tinfos) { + if (!(t != null && t.getId() != ti.getThreadId())) { + for (MonitorInfo mi : ti.getLockedMonitors()) { + if (mi.getIdentityHashCode() == oihc) { + return true; + } } } - return ReturnValue.FAILURE; + } + return false; + } + + protected static void run(Runnable r) { + if (TestInSeparateThread) { + Thread t = new Thread(new Runnable() { + @Override + public void run() { + beforeOSRLockTest(); + r.run(); + afterOSRLockTest(); + } + }); + t.start(); + try { + t.join(); + } catch (Throwable t1) { + throw new GraalError(t1); + } + } else { + beforeOSRLockTest(); + r.run(); + afterOSRLockTest(); + } + } + + private static boolean wasLocked() { + return isMonitorLockHeld(lock) || isMonitorLockHeld(lock1); + } + + protected static EconomicMap, Object> osrLockNoDeopt() { + EconomicMap, Object> overrides = OptionValues.newOptionMap(); + overrides.put(OnStackReplacementPhase.Options.DeoptAfterOSR, false); + overrides.put(OnStackReplacementPhase.Options.SupportOSRWithLocks, true); + return overrides; + } + + protected static EconomicMap, Object> osrLockDeopt() { + EconomicMap, Object> overrides = OptionValues.newOptionMap(); + overrides.put(OnStackReplacementPhase.Options.SupportOSRWithLocks, true); + return overrides; + } + + public static int SideEffectI; + + private static void lockOnObject(Object o, String msg) { + Thread t = new Thread(new Runnable() { + @Override + public void run() { + synchronized (o) { + SideEffectI = 1; + } + } + }); + t.start(); + try { + t.join(1000); + } catch (InterruptedException e) { + Assert.fail("Object " + msg + " was locked"); + } + } + + private static void beforeOSRLockTest() { + // try lock both objects + lockOnObject(lock, "lock"); + lockOnObject(lock1, "lock1"); + Assert.assertFalse(wasLocked()); + } + + private static void afterOSRLockTest() { + // try lock both objects + lockOnObject(lock, "lock"); + lockOnObject(lock1, "lock1"); + Assert.assertFalse(wasLocked()); + // force a safepoint and hope the inflated locks are deflated + System.gc(); + } + + // @Test + @SuppressWarnings("try") + public void testLockOSROuterImmediateDeoptAfter() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockDeopt()); + testOSR(options, "testOuterLockImmediateDeoptAfter"); + }); + } + + static class A { + + } + + static class B { + @SuppressWarnings("unused") + B(A a) { + + } + } + + HashMap> listeners = new HashMap<>(); + + public synchronized ReturnValue synchronizedSnippet() { + /* + * Test method for which liveness would conclude the original object is no longer alive + * although it is. + */ + Collection> allListeners = listeners.values(); + for (HashSet group : allListeners) { + GraalDirectives.blackhole(group); + } + return ReturnValue.SUCCESS; + } + + @Test + @SuppressWarnings("try") + public void testSynchronizedSnippet() { + GraalOSRLockTest instance = new GraalOSRLockTest(); + // enough entries to trigger OSR + for (int i = 0; i < 100000; i++) { + instance.listeners.put("hello" + i, null); + } + testOSR(getInitialOptions(), "synchronizedSnippet", instance); + Assert.assertFalse(isMonitorLockHeld(instance)); + } + + @Test + @SuppressWarnings("try") + public void testOSRTrivialLoop() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockDeopt()); + try { + testOSR(options, "testReduceOSRTrivialLoop"); + } catch (Throwable t) { + Assert.assertEquals("OSR compilation without OSR entry loop.", t.getMessage()); + } + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerImmediateDeoptAfter() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockDeopt()); + testOSR(options, "testOuterInnerLockImmediateDeoptAfter"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterCompileRestOfMethod() { + run(() -> { + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + testOSR(options, "testOuterLockCompileRestOfMethod"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerCompileRestOfMethod() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterInnerLockCompileRestOfMethod"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerLockDepthCompileRestOfMethod() { + run(() -> { + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + testOSR(options, "testOuterInnerLockDepth1CompileRestOfMethod"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerLockDepthDeopt() { + run(() -> { + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + testOSR(options, "testOuterInnerLockDepth1DeoptAfter"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerLockDepthRecursiveCompileRestOfMethod0() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterInnerLockDepth1RecursiveCompileRestOfMethod1"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerLockDepthRecursiveCompileRestOfMethod1() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterInnerLockDepth1RecursiveCompileRestOfMethod2"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterCompileRestOfMethodSubsequentLock() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterLockCompileRestOfMethodSubsequentLock"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSROuterInnerSameLockCompileRestOfMethod() { + run(() -> { + OptionValues options = new OptionValues(getInitialOptions(), osrLockNoDeopt()); + testOSR(options, "testOuterInnerSameLockCompileRestOfMethod"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSRRecursive() { + run(() -> { + // call it + testRecursiveLockingLeaf(); + ResolvedJavaMethod leaf = getResolvedJavaMethod("testRecursiveLockingLeaf"); + // profile it + leaf.reprofile(); + testRecursiveLockingLeaf(); + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + DebugContext debug = getDebugContext(options); + compile(debug, leaf, -1); + testOSR(options, "testRecursiveLockingRoot"); + }); + } + + @Test + @SuppressWarnings("try") + public void testLockOSRRecursiveLeafOSR() { + run(() -> { + testRecursiveRootNoOSR(); + ResolvedJavaMethod root = getResolvedJavaMethod("testRecursiveRootNoOSR"); + EconomicMap, Object> overrides = osrLockNoDeopt(); + overrides.put(HighTier.Options.Inline, false); + OptionValues options = new OptionValues(getInitialOptions(), overrides); + DebugContext debug = getDebugContext(options); + compile(debug, root, -1); + testOSR(options, "testRecursiveLeafOSR"); + // force a safepoint and hope the inflated locks are deflated + System.gc(); + // call the root to call into the leaf and enter the osr-ed code + testRecursiveRootNoOSR(); + + }); + } + + protected static int limit = 10000; + protected static Object lock = new Object(); + protected static Object lock1 = new Object(); + private static final boolean LOG = false; + + static { + // force identity hash code for easy displaced mark identification + int h1 = System.identityHashCode(lock); + int h2 = System.identityHashCode(lock1); + if (LOG) { + TTY.println("Forcing a system identity hashcode on lock object " + h1); + TTY.println("Forcing a system identity hashcode on lock1 object " + h2); + } + } + + public static ReturnValue testReduceOSRTrivialLoop() { + for (int i = 0; i < limit * limit; i++) { + GraalDirectives.blackhole(i); + if (GraalDirectives.inCompiledCode()) { + return ReturnValue.SUCCESS; + } + } + return ReturnValue.FAILURE; + } + + public static ReturnValue testOuterLockImmediateDeoptAfter() { + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + GraalDirectives.controlFlowAnchor(); + if (GraalDirectives.inCompiledCode()) { + throw new Error("Must not be part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockImmediateDeoptAfter() { + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + synchronized (lock1) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + GraalDirectives.deoptimize(); + return ret; + } + } + + public static ReturnValue testOuterLockCompileRestOfMethod() { + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + for (int i = 1; i < limit; i++) { + GraalDirectives.blackhole(i); + if (i % 1001 == 0) { + ret = ReturnValue.SUCCESS; + System.gc(); + } + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockCompileRestOfMethod() { + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + synchronized (lock1) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + System.gc(); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockDepth1CompileRestOfMethod() { + // testing the order of the lock releasing + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + synchronized (lock1) { + for (int i = 1; i < limit; i++) { + GraalDirectives.blackhole(i); + if (i % 1001 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (limit)) { + GraalDirectives.blackhole(ret); + System.gc(); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } else { + // lock 1 must be free + if (isMonitorLockHeld(lock1)) { + throw new Error("Lock 1 must have been released already"); + } + + // lock 2 must still be locked and cannot be acquired by another thread + if (!isMonitorLockHeldByThread(lock, Thread.currentThread())) { + throw new Error("Lock must not have been released already"); + } + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockDepth1DeoptAfter() { + // testing the order of the lock releasing + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + synchronized (lock1) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + GraalDirectives.controlFlowAnchor(); + GraalDirectives.deoptimize(); + if (GraalDirectives.inCompiledCode()) { + throw new Error("Must not part of compiled code"); + } + } + } + return ret; + } + + public static ReturnValue testOuterInnerLockDepth1RecursiveCompileRestOfMethod1() { + // testing the order of the lock releasing + ReturnValue ret = ReturnValue.FAILURE; + synchronized (lock) { + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testOuterInnerLockDepth1RecursiveCompileRestOfMethod2() { + // testing the order of the lock releasing + final Object l = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (l) { + synchronized (l) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testRecursiveLockingRoot() { + // testing the order of the lock releasing + final Object l = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (l) { + synchronized (l) { + for (int i = 1; i < limit; i++) { + GraalDirectives.blackhole(i); + testRecursiveLockingLeaf(); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; + } + } + + public static ReturnValue testRecursiveLockingLeaf() { + // testing the order of the lock releasing + final Object l = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (l) { + synchronized (l) { + for (int i = 1; i < limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + } + } + } + return ret; + } + } + + public static ReturnValue testRecursiveRootNoOSR() { + // testing the order of the lock releasing + final Object l = lock; + synchronized (l) { + ReturnValue ret = ReturnValue.FAILURE; + for (int i = 0; i < 5; i++) { + if (GraalDirectives.inCompiledCode()) { + ret = testRecursiveLeafOSR(); + } + GraalDirectives.controlFlowAnchor(); + if (ret == ReturnValue.FAILURE) { + return ret; + } + } + GraalDirectives.controlFlowAnchor(); + return ret; + } + } + + public static ReturnValue testRecursiveLeafOSR() { + ReturnValue ret = ReturnValue.FAILURE; + // lock is already locked by the caller + synchronized (lock) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + GraalDirectives.controlFlowAnchor(); + return ret; + } + } + + // test cases for optimizations + public static ReturnValue testOuterLockCompileRestOfMethodSubsequentLock() { + final Object monitor = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (monitor) { + for (int i = 1; i < 10 * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + synchronized (monitor) { + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + } + return ret; + + } + + public static ReturnValue testOuterInnerSameLockCompileRestOfMethod() { + final Object monitor = lock; + ReturnValue ret = ReturnValue.FAILURE; + synchronized (monitor) { + for (int i = 1; i < 10 * limit; i++) { + synchronized (monitor) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + if (GraalDirectives.inCompiledCode() && i + 33 > (10 * limit)) { + GraalDirectives.blackhole(ret); + } + } + } + } + GraalDirectives.controlFlowAnchor(); + if (!GraalDirectives.inCompiledCode()) { + throw new Error("Must part of compiled code"); + } + return ret; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java index 3ae96088676..a978dbf4bac 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java @@ -22,9 +22,9 @@ */ package org.graalvm.compiler.hotspot.test; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; +import org.junit.Assert; +import org.junit.Test; /** * Test on-stack-replacement with Graal. The test manually triggers a Graal OSR-compilation which is @@ -33,13 +33,29 @@ import org.graalvm.compiler.api.directives.GraalDirectives; public class GraalOSRTest extends GraalOSRTestBase { @Test - public void testOSR() { - testOSR("test"); + public void testOSR01() { + try { + testOSR(getInitialOptions(), "testReduceLoop"); + } catch (Throwable t) { + Assert.assertEquals("OSR compilation without OSR entry loop.", t.getMessage()); + } + } + + @Test + public void testOSR02() { + testOSR(getInitialOptions(), "testSequentialLoop"); + } + + @Test + public void testOSR03() { + testOSR(getInitialOptions(), "testNonReduceLoop"); } static int limit = 10000; - public static ReturnValue test() { + public static int sideEffect; + + public static ReturnValue testReduceLoop() { for (int i = 0; i < limit * limit; i++) { GraalDirectives.blackhole(i); if (GraalDirectives.inCompiledCode()) { @@ -49,4 +65,38 @@ public class GraalOSRTest extends GraalOSRTestBase { return ReturnValue.FAILURE; } + public static ReturnValue testSequentialLoop() { + ReturnValue ret = ReturnValue.FAILURE; + for (int i = 1; i < limit * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 7 == 0) { + ret = ReturnValue.SUCCESS; + } + } + GraalDirectives.controlFlowAnchor(); + if (sideEffect == 123) { + return ReturnValue.SIDE; + } + for (int i = 1; i < limit * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + } + } + GraalDirectives.controlFlowAnchor(); + return ret; + } + + public static ReturnValue testNonReduceLoop() { + ReturnValue ret = ReturnValue.FAILURE; + for (int i = 0; i < limit * limit; i++) { + GraalDirectives.blackhole(i); + if (i % 33 == 0) { + ret = ReturnValue.SUCCESS; + } + } + GraalDirectives.controlFlowAnchor(); + return ret; + } + } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java index 9742ebd1e1d..f0d53bb23d7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java @@ -23,19 +23,25 @@ package org.graalvm.compiler.hotspot.test; -import org.junit.Assert; +import java.util.Arrays; import org.graalvm.compiler.bytecode.Bytecode; +import org.graalvm.compiler.bytecode.BytecodeDisassembler; import org.graalvm.compiler.bytecode.BytecodeStream; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.hotspot.CompilationTask; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; import org.graalvm.compiler.java.BciBlockMapping; import org.graalvm.compiler.java.BciBlockMapping.BciBlock; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Assert; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; @@ -47,26 +53,30 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public abstract class GraalOSRTestBase extends GraalCompilerTest { - protected void testOSR(String methodName) { - ResolvedJavaMethod method = getResolvedJavaMethod(methodName); - testOSR(method); + protected void testOSR(OptionValues options, String methodName) { + testOSR(options, methodName, null); } - protected void testOSR(ResolvedJavaMethod method) { + protected void testOSR(OptionValues options, String methodName, Object receiver, Object... args) { + ResolvedJavaMethod method = getResolvedJavaMethod(methodName); + testOSR(options, method, receiver, args); + } + + protected void testOSR(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) { // invalidate any existing compiled code method.reprofile(); - compileOSR(method); - Result result = executeExpected(method, null); + compileOSR(options, method); + Result result = executeExpected(method, receiver, args); checkResult(result); } - private static void compile(ResolvedJavaMethod method, int bci) { + protected static void compile(DebugContext debug, ResolvedJavaMethod method, int bci) { HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); long jvmciEnv = 0L; HotSpotCompilationRequest request = new HotSpotCompilationRequest((HotSpotResolvedJavaMethod) method, bci, jvmciEnv); HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler(); - CompilationTask task = new CompilationTask(runtime, compiler, request, true, true); - HotSpotCompilationRequestResult result = task.runCompilation(); + CompilationTask task = new CompilationTask(runtime, compiler, request, true, true, debug.getOptions()); + HotSpotCompilationRequestResult result = task.runCompilation(debug); if (result.getFailure() != null) { throw new GraalError(result.getFailureMessage()); } @@ -76,22 +86,28 @@ public abstract class GraalOSRTestBase extends GraalCompilerTest { * Returns the target BCI of the first bytecode backedge. This is where HotSpot triggers * on-stack-replacement in case the backedge counter overflows. */ - private static int getBackedgeBCI(ResolvedJavaMethod method) { + private static int getBackedgeBCI(DebugContext debug, ResolvedJavaMethod method) { Bytecode code = new ResolvedJavaMethodBytecode(method); BytecodeStream stream = new BytecodeStream(code.getCode()); - BciBlockMapping bciBlockMapping = BciBlockMapping.create(stream, code); - assert bciBlockMapping.getLoopCount() == 1 : "Expected exactly one loop " + method; + OptionValues options = debug.getOptions(); + BciBlockMapping bciBlockMapping = BciBlockMapping.create(stream, code, options, debug); for (BciBlock block : bciBlockMapping.getBlocks()) { - int bci = block.startBci; - for (BciBlock succ : block.getSuccessors()) { - int succBci = succ.startBci; - if (succBci < bci) { - // back edge - return succBci; + if (block.startBci != -1) { + int bci = block.startBci; + for (BciBlock succ : block.getSuccessors()) { + if (succ.startBci != -1) { + int succBci = succ.startBci; + if (succBci < bci) { + // back edge + return succBci; + } + } } } } + TTY.println("Cannot find loop back edge with bytecode loops at:%s", Arrays.toString(bciBlockMapping.getLoopHeaders())); + TTY.println(new BytecodeDisassembler().disassemble(code)); return -1; } @@ -102,17 +118,19 @@ public abstract class GraalOSRTestBase extends GraalCompilerTest { Assert.assertEquals(ReturnValue.SUCCESS, result.returnValue); } - private void compileOSR(ResolvedJavaMethod method) { - int bci = getBackedgeBCI(method); - assert bci != -1; + private void compileOSR(OptionValues options, ResolvedJavaMethod method) { // ensure eager resolving - parseEager(method, AllowAssumptions.YES); - compile(method, bci); + StructuredGraph graph = parseEager(method, AllowAssumptions.YES, options); + DebugContext debug = graph.getDebug(); + int bci = getBackedgeBCI(debug, method); + assert bci != -1; + compile(debug, method, bci); } protected enum ReturnValue { SUCCESS, - FAILURE + FAILURE, + SIDE } public GraalOSRTestBase() { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java index 0d2e63f0747..f36c3384540 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java @@ -37,6 +37,7 @@ import org.junit.Assert; import org.junit.Test; import org.graalvm.compiler.code.CompilationResult; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins; import jdk.vm.ci.code.InstalledCode; @@ -48,8 +49,8 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class HotSpotCryptoSubstitutionTest extends HotSpotGraalCompilerTest { @Override - protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { - return getBackend().createDefaultInstalledCode(method, compResult); + protected InstalledCode addMethod(DebugContext debug, ResolvedJavaMethod method, CompilationResult compResult) { + return getBackend().createDefaultInstalledCode(debug, method, compResult); } SecretKey aesKey; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java index 1851b2619ea..2e28d06cce7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalCompilerTest.java @@ -30,6 +30,7 @@ import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.runtime.RuntimeProvider; import jdk.vm.ci.code.InstalledCode; @@ -54,9 +55,10 @@ public abstract class HotSpotGraalCompilerTest extends GraalCompilerTest { HotSpotGraalRuntimeProvider rt = (HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class); HotSpotProviders providers = rt.getHostBackend().getProviders(); CompilationIdentifier compilationId = runtime().getHostBackend().getCompilationIdentifier(method); - StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, compilationId); + OptionValues options = getInitialOptions(); + StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, compilationId, options, getDebugContext(options)); if (graph != null) { - return getCode(method, graph, true, true); + return getCode(method, graph, true, true, graph.getOptions()); } return null; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java new file mode 100644 index 00000000000..e2927cdf359 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.lang.management.ManagementFactory; +import java.lang.reflect.Field; + +import java.util.Arrays; +import javax.management.Attribute; +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanServer; +import javax.management.ObjectInstance; +import javax.management.ObjectName; + +import org.graalvm.compiler.debug.DebugOptions; +import org.graalvm.compiler.hotspot.HotSpotGraalMBean; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.test.GraalTest; +import org.graalvm.util.EconomicMap; +import org.junit.Assume; +import org.junit.Test; + +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +public class HotSpotGraalMBeanTest { + + public HotSpotGraalMBeanTest() { + // No support for registering Graal MBean yet on JDK9 (GR-4025). We cannot + // rely on an exception being thrown when accessing ManagementFactory.platformMBeanServer + // via reflection as recent JDK9 changes now allow this and issue a warning instead. + Assume.assumeTrue(GraalTest.Java8OrEarlier); + } + + @Test + public void registration() throws Exception { + ObjectName name; + + Field field = null; + try { + field = stopMBeanServer(); + } catch (Exception ex) { + if (ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) { + // skip on JDK9 + return; + } + } + assertNull("The platformMBeanServer isn't initialized now", field.get(null)); + + HotSpotGraalMBean bean = HotSpotGraalMBean.create(null); + assertNotNull("Bean created", bean); + + assertNull("It is not registered yet", bean.ensureRegistered(true)); + + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + + assertNotNull("Now the bean thinks it is registered", name = bean.ensureRegistered(true)); + + assertNotNull("And the bean is found", server.getObjectInstance(name)); + } + + private static Field stopMBeanServer() throws NoSuchFieldException, SecurityException, IllegalAccessException, IllegalArgumentException { + final Field field = ManagementFactory.class.getDeclaredField("platformMBeanServer"); + field.setAccessible(true); + field.set(null, null); + return field; + } + + @Test + public void readBeanInfo() throws Exception { + ObjectName name; + + assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer()); + + HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null); + assertNotNull("Bean is registered", name = realBean.ensureRegistered(false)); + final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + + ObjectInstance bean = server.getObjectInstance(name); + assertNotNull("Bean is registered", bean); + MBeanInfo info = server.getMBeanInfo(name); + assertNotNull("Info is found", info); + + MBeanAttributeInfo printCompilation = (MBeanAttributeInfo) findAttributeInfo("PrintCompilation", info); + assertNotNull("PrintCompilation found", printCompilation); + assertEquals("true/false", Boolean.class.getName(), printCompilation.getType()); + + Attribute printOn = new Attribute(printCompilation.getName(), Boolean.TRUE); + + Object before = server.getAttribute(name, printCompilation.getName()); + server.setAttribute(name, printOn); + Object after = server.getAttribute(name, printCompilation.getName()); + + assertNull("Default value was not set", before); + assertEquals("Changed to on", Boolean.TRUE, after); + } + + private static Object findAttributeInfo(String attrName, Object info) { + MBeanAttributeInfo printCompilation = null; + for (MBeanAttributeInfo attr : ((MBeanInfo) info).getAttributes()) { + if (attr.getName().equals(attrName)) { + assertTrue("Readable", attr.isReadable()); + assertTrue("Writable", attr.isWritable()); + printCompilation = attr; + break; + } + } + return printCompilation; + } + + @Test + public void optionsAreCached() throws Exception { + ObjectName name; + + assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer()); + + HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null); + + OptionValues original = new OptionValues(EconomicMap.create()); + + assertSame(original, realBean.optionsFor(original, null)); + + assertNotNull("Bean is registered", name = realBean.ensureRegistered(false)); + final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + + ObjectInstance bean = server.getObjectInstance(name); + assertNotNull("Bean is registered", bean); + MBeanInfo info = server.getMBeanInfo(name); + assertNotNull("Info is found", info); + + MBeanAttributeInfo dump = (MBeanAttributeInfo) findAttributeInfo("Dump", info); + + Attribute dumpTo1 = new Attribute(dump.getName(), 1); + + server.setAttribute(name, dumpTo1); + Object after = server.getAttribute(name, dump.getName()); + assertEquals(1, after); + + final OptionValues modified1 = realBean.optionsFor(original, null); + assertNotSame(original, modified1); + final OptionValues modified2 = realBean.optionsFor(original, null); + assertSame("Options are cached", modified1, modified2); + + } + + @Test + public void dumpOperation() throws Exception { + Field field = null; + try { + field = stopMBeanServer(); + } catch (Exception ex) { + if (ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) { + // skip on JDK9 + return; + } + } + assertNull("The platformMBeanServer isn't initialized now", field.get(null)); + + ObjectName name; + + assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer()); + + HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null); + + assertNotNull("Bean is registered", name = realBean.ensureRegistered(false)); + final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + + ObjectInstance bean = server.getObjectInstance(name); + assertNotNull("Bean is registered", bean); + + MBeanInfo info = server.getMBeanInfo(name); + assertNotNull("Info is found", info); + + final MBeanOperationInfo[] arr = info.getOperations(); + assertEquals("Currently three overloads", 3, arr.length); + MBeanOperationInfo dumpOp = null; + for (int i = 0; i < arr.length; i++) { + assertEquals("dumpMethod", arr[i].getName()); + if (arr[i].getSignature().length == 3) { + dumpOp = arr[i]; + } + } + assertNotNull("three args variant found", dumpOp); + + server.invoke(name, "dumpMethod", new Object[]{ + "java.util.Arrays", "asList", ":3" + }, null); + + MBeanAttributeInfo dump = (MBeanAttributeInfo) findAttributeInfo("Dump", info); + Attribute dumpTo1 = new Attribute(dump.getName(), ""); + server.setAttribute(name, dumpTo1); + Object after = server.getAttribute(name, dump.getName()); + assertEquals("", after); + + OptionValues empty = new OptionValues(EconomicMap.create()); + OptionValues unsetDump = realBean.optionsFor(empty, null); + final MetaAccessProvider metaAccess = jdk.vm.ci.runtime.JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess(); + ResolvedJavaMethod method = metaAccess.lookupJavaMethod(Arrays.class.getMethod("asList", Object[].class)); + final OptionValues forMethod = realBean.optionsFor(unsetDump, method); + assertNotSame(unsetDump, forMethod); + Object nothing = unsetDump.getMap().get(DebugOptions.Dump); + assertEquals("Empty string", "", nothing); + + Object specialValue = forMethod.getMap().get(DebugOptions.Dump); + assertEquals(":3", specialValue); + + OptionValues normalMethod = realBean.optionsFor(unsetDump, null); + Object noSpecialValue = normalMethod.getMap().get(DebugOptions.Dump); + assertEquals("Empty string", "", noSpecialValue); + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMonitorValueTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMonitorValueTest.java index 2546b78489d..f4b8bc65079 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMonitorValueTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMonitorValueTest.java @@ -34,6 +34,7 @@ import org.junit.Test; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import jdk.vm.ci.code.BytecodeFrame; @@ -46,7 +47,7 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class HotSpotMonitorValueTest extends GraalCompilerTest { @Override - protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { + protected InstalledCode addMethod(DebugContext debug, ResolvedJavaMethod method, CompilationResult compResult) { for (Infopoint i : compResult.getInfopoints()) { if (i instanceof Call) { Call call = (Call) i; @@ -75,7 +76,7 @@ public class HotSpotMonitorValueTest extends GraalCompilerTest { } assertDeepEquals(lock3.getOwner(), lock4.getOwner()); assertThat(lock1.getOwner(), not(lock2.getOwner())); - return super.addMethod(method, compResult); + return super.addMethod(debug, method, compResult); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotNodeSubstitutionsTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotNodeSubstitutionsTest.java index fe000286b9b..e756b179615 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotNodeSubstitutionsTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotNodeSubstitutionsTest.java @@ -22,15 +22,15 @@ */ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - import org.junit.Test; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.test.MethodSubstitutionTest; /** @@ -40,7 +40,9 @@ public class HotSpotNodeSubstitutionsTest extends MethodSubstitutionTest { @Test public void test() { - StructuredGraph graph = new StructuredGraph(AllowAssumptions.YES, INVALID_COMPILATION_ID); + OptionValues options = getInitialOptions(); + DebugContext debug = getDebugContext(options); + StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).build(); test("getNodeClass", ConstantNode.forInt(42, graph)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java index 549a69b238d..1265cd91f7f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotResolvedJavaFieldTest.java @@ -36,7 +36,7 @@ import java.lang.reflect.Method; import org.junit.Assert; import org.junit.Test; - +import org.graalvm.compiler.core.common.util.Util; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; @@ -52,18 +52,24 @@ public class HotSpotResolvedJavaFieldTest extends HotSpotGraalCompilerTest { private static final Class[] classesWithInternalFields = {Class.class, ClassLoader.class}; private static final Method createFieldMethod; + private static final Field indexField; static { - Method ret = null; + Method m = null; + Field f = null; try { Class typeImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedObjectTypeImpl"); - ret = typeImpl.getDeclaredMethod("createField", String.class, JavaType.class, long.class, int.class); - ret.setAccessible(true); - } catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) { - e.printStackTrace(); + m = typeImpl.getDeclaredMethod("createField", JavaType.class, long.class, int.class, int.class); + Util.setAccessible(m, true); + Class fieldImpl = Class.forName("jdk.vm.ci.hotspot.HotSpotResolvedJavaFieldImpl"); + f = fieldImpl.getDeclaredField("index"); + Util.setAccessible(f, true); + } catch (Exception e) { + throw new AssertionError(e); } - createFieldMethod = ret; + createFieldMethod = m; + indexField = f; } /** @@ -96,21 +102,22 @@ public class HotSpotResolvedJavaFieldTest extends HotSpotGraalCompilerTest { /** * Tests that {@code HotSpotResolvedObjectType#createField(String, JavaType, long, int)} always - * returns the same object for an internal field. + * returns an {@linkplain ResolvedJavaField#equals(Object) equivalent} object for an internal + * field. * * @throws InvocationTargetException * @throws IllegalArgumentException * @throws IllegalAccessException */ @Test - public void testCachingForInternalFields() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - Assert.assertTrue("HotSpotResolvedObjectTypeImpl.createField method not found", createFieldMethod != null); + public void testEquivalenceForInternalFields() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { for (Class c : classesWithInternalFields) { HotSpotResolvedObjectType type = HotSpotResolvedObjectType.fromObjectClass(c); for (ResolvedJavaField field : type.getInstanceFields(false)) { if (field.isInternal()) { HotSpotResolvedJavaField expected = (HotSpotResolvedJavaField) field; - ResolvedJavaField actual = (ResolvedJavaField) createFieldMethod.invoke(type, expected.getName(), expected.getType(), expected.offset(), expected.getModifiers()); + int index = indexField.getInt(expected); + ResolvedJavaField actual = (ResolvedJavaField) createFieldMethod.invoke(type, expected.getType(), expected.offset(), expected.getModifiers(), index); Assert.assertEquals(expected, actual); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStampMemoryAccessTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStampMemoryAccessTest.java new file mode 100644 index 00000000000..74bfeaa3b9e --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStampMemoryAccessTest.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.test; + +import org.graalvm.compiler.core.common.CompressEncoding; +import org.graalvm.compiler.core.common.type.ObjectStamp; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.hotspot.nodes.type.HotSpotNarrowOopStamp; +import org.junit.Assume; +import org.junit.Ignore; +import org.junit.Test; + +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MemoryAccessProvider; + +public class HotSpotStampMemoryAccessTest extends HotSpotGraalCompilerTest { + + @Ignore("not all versions are safe yet") + @Test + public void testReadNarrowObject() { + CompressEncoding oopEncoding = runtime().getVMConfig().getOopEncoding(); + Assume.assumeTrue("Compressed oops must be enabled", runtime().getVMConfig().useCompressedOops); + MemoryAccessProvider memory = getConstantReflection().getMemoryAccessProvider(); + JavaConstant base = getSnippetReflection().forObject(""); + ObjectStamp stamp = (ObjectStamp) StampFactory.forKind(JavaKind.Object); + Stamp narrowStamp = HotSpotNarrowOopStamp.compressed(stamp, oopEncoding); + assertTrue(narrowStamp.readConstant(memory, base, 128) == null); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/InstalledCodeExecuteHelperTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/InstalledCodeExecuteHelperTest.java index 9d9e1598bec..3d13cb47f14 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/InstalledCodeExecuteHelperTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/InstalledCodeExecuteHelperTest.java @@ -24,15 +24,15 @@ package org.graalvm.compiler.hotspot.test; import static java.lang.reflect.Modifier.isStatic; -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.StructuredGraph.Builder; +import org.graalvm.compiler.phases.PhaseSuite; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Assert; +import org.junit.Test; import jdk.vm.ci.code.InvalidInstalledCodeException; import jdk.vm.ci.hotspot.HotSpotInstalledCode; @@ -76,9 +76,10 @@ public class InstalledCodeExecuteHelperTest extends GraalCompilerTest { } @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - StructuredGraph graph = super.parseEager(m, allowAssumptions, compilationId); + protected StructuredGraph parse(Builder builder, PhaseSuite graphBuilderSuite) { + StructuredGraph graph = super.parse(builder, graphBuilderSuite); if (argsToBind != null) { + ResolvedJavaMethod m = graph.method(); Object receiver = isStatic(m.getModifiers()) ? null : this; Object[] args = argsWithReceiver(receiver, argsToBind); JavaType[] parameterTypes = m.toParameterTypes(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java index 65676eff909..d0ad9c8c978 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIInfopointErrorTest.java @@ -29,14 +29,13 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; import java.util.function.Consumer; -import org.junit.Test; - import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Scope; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder; import org.graalvm.compiler.lir.FullInfopointOp; @@ -51,8 +50,10 @@ import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.junit.Test; import jdk.vm.ci.code.BytecodeFrame; +import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.VirtualObject; import jdk.vm.ci.code.site.InfopointReason; import jdk.vm.ci.common.JVMCIError; @@ -133,15 +134,20 @@ public class JVMCIInfopointErrorTest extends GraalCompilerTest { } private void test(TestSpec spec) { + test(getDebugContext(), spec); + } + + private void test(DebugContext debug, TestSpec spec) { ResolvedJavaMethod method = getResolvedJavaMethod("testMethod"); - StructuredGraph graph = parseForCompile(method); + StructuredGraph graph = parseForCompile(method, debug); TestNode test = graph.add(new TestNode(spec)); graph.addAfterFixed(graph.start(), test); CompilationResult compResult = compile(method, graph); - HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(method, null, compResult); - getCodeCache().addCode(method, compiledCode, null, null); + CodeCacheProvider codeCache = getCodeCache(); + HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, method, null, compResult); + codeCache.addCode(method, compiledCode, null, null); } @Test(expected = JVMCIError.class) @@ -264,12 +270,13 @@ public class JVMCIInfopointErrorTest extends GraalCompilerTest { @SuppressWarnings("try") @Test(expected = Error.class) public void testUnknownJavaValue() { - try (DebugConfigScope s = Debug.setConfig(Debug.silentConfig())) { + DebugContext debug = DebugContext.create(getInitialOptions(), DebugHandlersFactory.LOADER); + try (Scope s = debug.disable()) { /* * Expected: either AssertionError or GraalError, depending on whether the unit test run * is with assertions enabled or disabled. */ - test((tool, state, safepoint) -> { + test(debug, (tool, state, safepoint) -> { LIRFrameState newState = modifyTopFrame(state, new JavaValue[]{new UnknownJavaValue()}, new JavaKind[]{JavaKind.Int}, 1, 0, 0); safepoint.accept(newState); }); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java index 57c9776498d..bb968a964b8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/LoadJavaMirrorWithKlassTest.java @@ -30,8 +30,7 @@ import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.Suites; import jdk.vm.ci.meta.JavaKind; @@ -58,10 +57,12 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest { @Override @SuppressWarnings("try") - protected Suites createSuites() { - try (OverrideScope s = OptionValue.override(GraalOptions.ImmutableCode, true)) { - return super.createSuites(); - } + protected Suites createSuites(OptionValues options) { + return super.createSuites(getOptions()); + } + + private static OptionValues getOptions() { + return new OptionValues(getInitialOptions(), GraalOptions.ImmutableCode, true); } @Override @@ -80,7 +81,7 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest { @Test public void testClassConstant() { - test("classConstant"); + test(getOptions(), "classConstant"); } public static Class primitiveClassConstant() { @@ -89,7 +90,7 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest { @Test public void testPrimitiveClassConstant() { - test("primitiveClassConstant"); + test(getOptions(), "primitiveClassConstant"); } public static Wrapper compressedClassConstant(Wrapper w) { @@ -100,7 +101,7 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest { @Test public void testCompressedClassConstant() { ArgSupplier arg = () -> new Wrapper(); - test("compressedClassConstant", arg); + test(getOptions(), "compressedClassConstant", arg); } public static Wrapper compressedPrimitiveClassConstant(Wrapper w) { @@ -111,6 +112,6 @@ public class LoadJavaMirrorWithKlassTest extends GraalCompilerTest { @Test public void testCompressedPrimitiveClassConstant() { ArgSupplier arg = () -> new Wrapper(); - test("compressedPrimitiveClassConstant", arg); + test(getOptions(), "compressedPrimitiveClassConstant", arg); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java index f12b0ba0a4e..587b6d2ccf3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/MemoryUsageBenchmark.java @@ -22,18 +22,14 @@ */ package org.graalvm.compiler.hotspot.test; -import static org.graalvm.compiler.debug.internal.MemUseTrackerImpl.getCurrentThreadAllocatedBytes; +import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes; import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.core.test.AllocSpy; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugEnvironment; -import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.hotspot.CompilationTask; -import org.graalvm.compiler.hotspot.CompileTheWorld; -import org.graalvm.compiler.hotspot.CompileTheWorldOptions; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -53,7 +49,7 @@ import jdk.vm.ci.runtime.JVMCICompiler; * Memory analysis for a {@link CompileTheWorld} execution can also be performed. For example: * *
      - *     mx --vm server vm -XX:-UseJVMCIClassLoader -Dgraal.CompileTheWorldClasspath=$HOME/SPECjvm2008/SPECjvm2008.jar -cp @org.graalvm.compiler.hotspot.test org.graalvm.compiler.hotspot.test.MemoryUsageBenchmark
      + *     mx vm -XX:-UseJVMCIClassLoader -DCompileTheWorld.Classpath=$HOME/SPECjvm2008/SPECjvm2008.jar -cp @org.graalvm.compiler.hotspot.test org.graalvm.compiler.hotspot.test.MemoryUsageBenchmark
        * 
      */ public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { @@ -124,10 +120,6 @@ public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { // may include processing command line options used by the latter. Graal.getRuntime(); - // Ensure a debug configuration for this thread is initialized - if (Debug.isEnabled() && DebugScope.getConfig() == null) { - DebugEnvironment.initialize(System.out); - } new MemoryUsageBenchmark().run(); } @@ -144,7 +136,7 @@ public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); int entryBCI = JVMCICompiler.INVOCATION_ENTRY_BCI; HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, entryBCI, jvmciEnv); - CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false); + CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false, getInitialOptions()); task.runCompilation(); } } @@ -161,7 +153,9 @@ public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { try (AllocSpy as = AllocSpy.open(methodName)) { HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); HotSpotCompilationRequest request = new HotSpotCompilationRequest(method, JVMCICompiler.INVOCATION_ENTRY_BCI, jvmciEnv); - CompilationTask task = new CompilationTask(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), request, true, false); + HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) runtime.getCompiler(); + OptionValues options = getInitialOptions(); + CompilationTask task = new CompilationTask(runtime, compiler, request, true, false, options); task.runCompilation(); } } @@ -185,9 +179,10 @@ public class MemoryUsageBenchmark extends HotSpotGraalCompilerTest { public void run() { compileAndTime("simple"); compileAndTime("complex"); - if (CompileTheWorldOptions.CompileTheWorldClasspath.getValue() != CompileTheWorld.SUN_BOOT_CLASS_PATH) { + OptionValues options = CompileTheWorld.loadOptions(getInitialOptions()); + if (CompileTheWorld.Options.Classpath.getValue(options) != CompileTheWorld.SUN_BOOT_CLASS_PATH) { HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime(); - CompileTheWorld ctw = new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler()); + CompileTheWorld ctw = new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), options); try { ctw.compile(); } catch (Throwable e) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ObjectCloneTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ObjectCloneTest.java new file mode 100644 index 00000000000..02baa30a806 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ObjectCloneTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.test; + +import java.util.ArrayList; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.junit.Test; + +/** + * Exercise intrinsification of {@link Object#clone}. + */ +public class ObjectCloneTest extends GraalCompilerTest { + + public static Object cloneArray(int[] array) { + return array.clone(); + } + + public static Object cloneList(ArrayList list) { + return list.clone(); + } + + static class ObjectCloneable implements Cloneable { + int field; + + @Override + protected Object clone() throws CloneNotSupportedException { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + throw new AssertionError(); + } + } + } + + static class CloneableSubclass extends ObjectCloneable { + + } + + /* + * This test checks that the ObjectCloneNode doesn't accidentally inject non-nullness into the + * graph which is later removed. + */ + public static Object notCloneable(ObjectCloneable cloneable) throws CloneNotSupportedException { + ObjectCloneable clone = (ObjectCloneable) cloneable.clone(); + return clone.getClass(); + } + + @Test + public void testNotIntrinsified() throws Throwable { + test("notCloneable", new CloneableSubclass()); + } + + @Test + public void testArray() throws Throwable { + test("cloneArray", new int[]{1, 2, 4, 3}); + } + + @Test + public void testList() throws Throwable { + ArrayList list = new ArrayList<>(); + for (int i = 0; i < 4; i++) { + list.add(i); + } + test("cloneList", list); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/OptionsInFileTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/OptionsInFileTest.java new file mode 100644 index 00000000000..10755c37352 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/OptionsInFileTest.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.test; + +import static org.graalvm.compiler.debug.DebugOptions.Dump; +import static org.graalvm.compiler.debug.DebugOptions.MethodFilter; +import static org.graalvm.compiler.debug.DebugOptions.PrintGraph; +import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine; +import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.util.List; + +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.test.SubprocessUtil; +import org.graalvm.compiler.test.SubprocessUtil.Subprocess; +import org.junit.Assert; +import org.junit.Test; + +/** + * Tests reading options from a file specified by the {@code graal.options.file}. + */ +public class OptionsInFileTest extends GraalCompilerTest { + @Test + public void test() throws IOException, InterruptedException { + String methodFilterValue = "a very unlikely method name"; + String debugFilterValue = "a very unlikely debug scope"; + File optionsFile = File.createTempFile("options", ".properties").getAbsoluteFile(); + try { + Assert.assertFalse(methodFilterValue.equals(MethodFilter.getDefaultValue())); + Assert.assertFalse(debugFilterValue.equals(Dump.getDefaultValue())); + Assert.assertTrue(PrintGraph.getDefaultValue()); + + try (PrintStream out = new PrintStream(new FileOutputStream(optionsFile))) { + out.println(MethodFilter.getName() + "=" + methodFilterValue); + out.println(Dump.getName() + "=" + debugFilterValue); + out.println(PrintGraph.getName() + " = false"); + } + + List vmArgs = withoutDebuggerArguments(getVMCommandLine()); + vmArgs.removeIf(a -> a.startsWith("-Dgraal.")); + vmArgs.add("-Dgraal.options.file=" + optionsFile); + vmArgs.add("-XX:+JVMCIPrintProperties"); + Subprocess proc = SubprocessUtil.java(vmArgs); + String[] expected = { + "graal.MethodFilter := \"a very unlikely method name\"", + "graal.Dump := \"a very unlikely debug scope\"", + "graal.PrintGraph := false"}; + for (String line : proc.output) { + for (int i = 0; i < expected.length; i++) { + if (expected[i] != null && line.contains(expected[i])) { + expected[i] = null; + } + } + } + + for (int i = 0; i < expected.length; i++) { + if (expected[i] != null) { + Assert.fail(String.format("Did not find '%s' in output of command:%n%s", expected[i], proc)); + } + } + } finally { + optionsFile.delete(); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java new file mode 100644 index 00000000000..06d12bc8733 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.test; + +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin; +import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; +import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; +import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; +import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase; +import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase; +import org.graalvm.compiler.hotspot.phases.aot.ReplaceConstantNodesPhase; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.common.CanonicalizerPhase; +import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Assert; +import org.junit.Test; + +public class ReplaceConstantNodesPhaseTest extends HotSpotGraalCompilerTest { + private final GraalHotSpotVMConfig config = runtime().getVMConfig(); + + @Override + protected Plugins getDefaultGraphBuilderPlugins() { + Plugins plugins = super.getDefaultGraphBuilderPlugins(); + plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin()); + return plugins; + } + + public static class X { + public static int x; + public static int y; + public static int z; + public static Object o; + } + + public static class Y extends X { + public static int a; + public static int b; + } + + public static int a; + + public static void assignFields() { + X.x = 1; + X.y = 2; + X.z = 3; + } + + public static void assignFieldsInBranches(boolean x) { + if (x) { + X.y = 1; + } else { + X.z = 2; + } + } + + public static void assignFieldsWithDominatingInit(boolean x) { + X.x = 1; + if (x) { + X.y = 2; + } else { + X.z = 3; + } + } + + public static void assignString() { + X.o = "foo"; + } + + public static void assignToParentAndChild() { + Y.a = 1; + X.x = 2; + } + + public static void assignToThis() { + a = 1; + } + + public static void assignFieldsWithDominatingInitOfParent(boolean x) { + Y.a = 1; + if (x) { + X.y = 2; + } else { + X.z = 3; + } + Y.b = 4; + } + + private void test(String name, int expectedInits, int expectedResolves, int expectedLoads) { + StructuredGraph graph = parseEager(name, AllowAssumptions.NO, new OptionValues(getInitialOptions(), GraalOptions.GeneratePIC, true)); + HighTierContext highTierContext = getDefaultHighTierContext(); + CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); + new EliminateRedundantInitializationPhase().apply(graph, highTierContext); + new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext); + new LoadJavaMirrorWithKlassPhase(config).apply(graph, highTierContext); + new ReplaceConstantNodesPhase(false).apply(graph, highTierContext); + Assert.assertEquals(expectedInits, graph.getNodes().filter(InitializeKlassNode.class).count()); + Assert.assertEquals(expectedResolves, graph.getNodes().filter(ResolveConstantNode.class).count()); + Assert.assertEquals(expectedLoads, graph.getNodes().filter(LoadConstantIndirectlyNode.class).count()); + } + + @Test + public void test1() { + test("assignFields", 1, 0, 0); + } + + @Test + public void test2() { + test("assignFieldsWithDominatingInit", 1, 0, 0); + } + + @Test + public void test3() { + test("assignString", 1, 1, 0); + } + + @Test + public void test4() { + test("assignToParentAndChild", 1, 1, 0); + } + + @Test + public void test5() { + test("assignToThis", 0, 0, 1); + } + + @Test + public void test6() { + test("assignFieldsWithDominatingInitOfParent", 1, 1, 0); + } + + @Test + public void test7() { + test("assignFieldsInBranches", 2, 1, 0); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java index 0333f9a973f..ec4aa5a8df8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java @@ -23,12 +23,11 @@ package org.graalvm.compiler.hotspot.test; import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - import java.util.List; -import java.util.Map; import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.HotSpotGraalCompiler; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -37,8 +36,10 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plu import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.graalvm.util.EconomicMap; import org.junit.Test; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; @@ -60,16 +61,18 @@ public class TestIntrinsicCompiles extends GraalCompilerTest { Plugins graphBuilderPlugins = providers.getGraphBuilderPlugins(); InvocationPlugins invocationPlugins = graphBuilderPlugins.getInvocationPlugins(); - Map> bindings = invocationPlugins.getBindings(true); + EconomicMap> bindings = invocationPlugins.getBindings(true); HotSpotVMConfigStore store = rt.getVMConfig().getStore(); List intrinsics = store.getIntrinsics(); + OptionValues options = getInitialOptions(); + DebugContext debug = getDebugContext(options); for (VMIntrinsicMethod intrinsic : intrinsics) { InvocationPlugin plugin = CheckGraalIntrinsics.findPlugin(bindings, intrinsic); if (plugin != null) { if (plugin instanceof MethodSubstitutionPlugin) { ResolvedJavaMethod method = CheckGraalIntrinsics.resolveIntrinsic(getMetaAccess(), intrinsic); if (!method.isNative()) { - StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, INVALID_COMPILATION_ID); + StructuredGraph graph = compiler.getIntrinsicGraph(method, providers, INVALID_COMPILATION_ID, options, debug); getCode(method, graph); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java index 14ab256a2fa..3521e03b66c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierAdditionTest.java @@ -27,11 +27,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import java.lang.ref.WeakReference; -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; @@ -53,6 +49,8 @@ import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.common.inlining.policy.InlineEverythingPolicy; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.MidTierContext; +import org.junit.Assert; +import org.junit.Test; import jdk.vm.ci.hotspot.HotSpotInstalledCode; import jdk.vm.ci.meta.JavaConstant; @@ -256,8 +254,9 @@ public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest { @SuppressWarnings("try") private void testHelper(final String snippetName, final int expectedBarriers) throws Exception, SecurityException { ResolvedJavaMethod snippet = getResolvedJavaMethod(snippetName); - try (Scope s = Debug.scope("WriteBarrierAdditionTest", snippet)) { - StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO); + DebugContext debug = getDebugContext(); + try (DebugContext.Scope s = debug.scope("WriteBarrierAdditionTest", snippet)) { + StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO, debug); HighTierContext highContext = getDefaultHighTierContext(); MidTierContext midContext = new MidTierContext(getProviders(), getTargetProvider(), OptimisticOptimizations.ALL, graph.getProfilingInfo()); new InliningPhase(new InlineEverythingPolicy(), new CanonicalizerPhase()).apply(graph, highContext); @@ -266,7 +265,7 @@ public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest { new GuardLoweringPhase().apply(graph, midContext); new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, midContext); new WriteBarrierAdditionPhase(config).apply(graph); - Debug.dump(Debug.BASIC_LOG_LEVEL, graph, "After Write Barrier Addition"); + debug.dump(DebugContext.BASIC_LEVEL, graph, "After Write Barrier Addition"); int barriers = 0; if (config.useG1GC) { @@ -305,7 +304,7 @@ public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest { } } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java index ce367b0831e..4c3a48468c4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java @@ -23,18 +23,11 @@ package org.graalvm.compiler.hotspot.test; import java.util.List; -import java.util.Map; -import org.junit.Assert; -import org.junit.Test; - -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.DebugConfig; -import org.graalvm.compiler.debug.DebugConfigScope; +import org.graalvm.compiler.debug.DebugCloseable; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Scope; import org.graalvm.compiler.debug.DebugDumpScope; -import org.graalvm.compiler.debug.internal.DebugScope; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier; @@ -66,6 +59,10 @@ import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.MidTierContext; +import org.graalvm.util.EconomicMap; +import org.graalvm.word.LocationIdentity; +import org.junit.Assert; +import org.junit.Test; import jdk.vm.ci.meta.ResolvedJavaField; @@ -306,7 +303,7 @@ public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest { test("test6Snippet", 5, new int[]{1, 2}); } - @Test(expected = AssertionError.class) + @Test public void test23() { test("test6Snippet", 5, new int[]{3}); } @@ -649,8 +646,9 @@ public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest { @SuppressWarnings("try") private void testPredicate(final String snippet, final GraphPredicate expectedBarriers, final int... removedBarrierIndices) { - try (Scope d = Debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet))) { - final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES); + DebugContext debug = getDebugContext(); + try (DebugCloseable d = debug.disableIntercept(); DebugContext.Scope s = debug.scope("WriteBarrierVerificationTest", new DebugDumpScope(snippet))) { + final StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES, debug); HighTierContext highTierContext = getDefaultHighTierContext(); new InliningPhase(new CanonicalizerPhase()).apply(graph, highTierContext); @@ -712,7 +710,7 @@ public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest { } @Override - protected Map processLoop(LoopBeginNode loop, Boolean initialState) { + protected EconomicMap processLoop(LoopBeginNode loop, Boolean initialState) { return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates; } @@ -727,10 +725,7 @@ public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest { } }; - DebugConfig debugConfig = DebugScope.getConfig(); - DebugConfig fixedConfig = debugConfig == null ? null - : Debug.fixedConfig(0, 0, false, false, false, false, false, debugConfig.dumpHandlers(), debugConfig.verifyHandlers(), debugConfig.output()); - try (DebugConfigScope s = Debug.setConfig(fixedConfig)) { + try (Scope disabled = debug.disable()) { ReentrantNodeIterator.apply(closure, graph.start(), false); new WriteBarrierVerificationPhase(config).apply(graph); } catch (AssertionError error) { @@ -742,7 +737,7 @@ public class WriteBarrierVerificationTest extends HotSpotGraalCompilerTest { throw error; } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java index 3a93d463936..cec7868e3c7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/AOTGraalHotSpotVMConfig.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.hotspot; +import org.graalvm.compiler.core.common.CompressEncoding; + import jdk.vm.ci.hotspot.HotSpotVMConfigStore; public class AOTGraalHotSpotVMConfig extends GraalHotSpotVMConfig { @@ -30,11 +32,15 @@ public class AOTGraalHotSpotVMConfig extends GraalHotSpotVMConfig { public AOTGraalHotSpotVMConfig(HotSpotVMConfigStore store) { super(store); - // In AOT, force the shift to be always equal to alignment therefore avoiding zero-shift. + // AOT captures VM settings during compilation. For compressed oops this + // presents a problem for the case when the VM selects a zero-shift mode + // (i.e., when the heap is less than 4G). Compiling an AOT binary with + // zero-shift limits its usability. As such we force the shift to be + // always equal to alignment to avoid emitting zero-shift AOT code. CompressEncoding vmOopEncoding = super.getOopEncoding(); - aotOopEncoding = new CompressEncoding(vmOopEncoding.base, vmOopEncoding.alignment, vmOopEncoding.alignment); + aotOopEncoding = new CompressEncoding(vmOopEncoding.getBase(), logMinObjAlignment()); CompressEncoding vmKlassEncoding = super.getKlassEncoding(); - aotKlassEncoding = new CompressEncoding(vmKlassEncoding.base, vmKlassEncoding.alignment, vmKlassEncoding.alignment); + aotKlassEncoding = new CompressEncoding(vmKlassEncoding.getBase(), logKlassAlignment); assert check(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java index 7e4ac5fe897..2fc58b3e698 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/BootstrapWatchDog.java @@ -23,7 +23,7 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.hotspot.HotSpotGraalCompiler.fmt; -import static org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory.GRAAL_OPTION_PROPERTY_PREFIX; +import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX; import java.util.Arrays; import java.util.HashMap; @@ -32,8 +32,9 @@ import java.util.concurrent.atomic.AtomicInteger; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.CompilationRequest; @@ -58,9 +59,9 @@ final class BootstrapWatchDog extends Thread { // @formatter:off @Option(help = "Ratio of the maximum compilation rate below which the bootstrap compilation rate must not fall " + "(0 or less disables monitoring).", type = OptionType.Debug) - public static final OptionValue BootstrapWatchDogCriticalRateRatio = new OptionValue<>(0.25D); + public static final OptionKey BootstrapWatchDogCriticalRateRatio = new OptionKey<>(0.25D); @Option(help = "Maximum time in minutes to spend bootstrapping (0 to disable this limit).", type = OptionType.Debug) - public static final OptionValue BootstrapTimeout = new OptionValue<>(15D); + public static final OptionKey BootstrapTimeout = new OptionKey<>(15D); // @formatter:on } @@ -88,13 +89,18 @@ final class BootstrapWatchDog extends Thread { * {@code null}. */ static BootstrapWatchDog maybeCreate(HotSpotGraalRuntimeProvider graalRuntime) { - return MAX_RATE_DECREASE <= 0.0D && TIMEOUT == 0 ? null : new BootstrapWatchDog(graalRuntime); + OptionValues options = graalRuntime.getOptions(); + int timeout = (int) (Options.BootstrapTimeout.getValue(options) * 60); + double maxRateDecrease = Options.BootstrapWatchDogCriticalRateRatio.getValue(options); + return maxRateDecrease <= 0.0D && timeout == 0 ? null : new BootstrapWatchDog(graalRuntime, timeout, maxRateDecrease); } - private BootstrapWatchDog(HotSpotGraalRuntimeProvider graalRuntime) { + private BootstrapWatchDog(HotSpotGraalRuntimeProvider graalRuntime, int timeout, double maxRateDecrease) { this.setName(getClass().getSimpleName()); this.start(); this.graalRuntime = graalRuntime; + this.timeout = timeout; + this.maxRateDecrease = maxRateDecrease; } /** @@ -115,13 +121,13 @@ final class BootstrapWatchDog extends Thread { /** * Time in seconds before stopping a bootstrap. */ - private static final int TIMEOUT = (int) (Options.BootstrapTimeout.getValue() * 60); + private final int timeout; /** * The watch dog {@link #hitCriticalCompilationRateOrTimeout() hits} a critical compilation rate * if the current compilation rate falls below this ratio of the maximum compilation rate. */ - private static final double MAX_RATE_DECREASE = Options.BootstrapWatchDogCriticalRateRatio.getValue(); + private final double maxRateDecrease; @Override public void run() { @@ -142,16 +148,16 @@ final class BootstrapWatchDog extends Thread { } if (rate > maxRate) { maxRate = rate; - } else if (rate < (maxRate * MAX_RATE_DECREASE)) { + } else if (rate < (maxRate * maxRateDecrease)) { TTY.printf("%nAfter %.2f seconds bootstrapping, compilation rate is %.2f compilations per second " + - "which is below %.2f times the max compilation rate of %.2f%n", seconds(elapsed), rate, MAX_RATE_DECREASE, maxRate); + "which is below %.2f times the max compilation rate of %.2f%n", seconds(elapsed), rate, maxRateDecrease, maxRate); TTY.printf("To enable monitoring of long running individual compilations, re-run with -D%s%s=%.2f%n", GRAAL_OPTION_PROPERTY_PREFIX, CompilationWatchDog.Options.CompilationWatchDogStartDelay.getName(), seconds(elapsed) - 5); hitCriticalRateOrTimeout = true; return; } - if (elapsed > TIMEOUT * 1000) { + if (elapsed > timeout * 1000) { if (requestsAtTimeout == null) { requestsAtTimeout = snapshotRequests(); stacksAtTimeout = new HashMap<>(); @@ -205,7 +211,7 @@ final class BootstrapWatchDog extends Thread { } /** - * Queries whether a critically low compilation rate or {@link #TIMEOUT} occurred. + * Queries whether a critically low compilation rate or {@link #timeout} occurred. */ boolean hitCriticalCompilationRateOrTimeout() { return hitCriticalRateOrTimeout; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.java index e5f0f4ecc4c..824641be1b0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.java @@ -24,7 +24,6 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.hotspot.HotSpotGraalCompiler.fmt; import static org.graalvm.compiler.hotspot.HotSpotGraalCompiler.str; - import java.util.Comparator; import java.util.HashMap; import java.util.Map; @@ -35,9 +34,8 @@ import java.util.TreeSet; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; - +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.options.OptionKey; import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -47,12 +45,15 @@ class CompilationCounters { // @formatter:off @Option(help = "The number of compilations allowed for any method before " + "the VM exits (a value of 0 means there is no limit).", type = OptionType.Debug) - public static final OptionValue CompilationCountLimit = new StableOptionValue<>(0); + public static final OptionKey CompilationCountLimit = new OptionKey<>(0); // @formatter:on } - CompilationCounters() { + private final OptionValues options; + + CompilationCounters(OptionValues options) { TTY.println("Warning: Compilation counters enabled, excessive recompilation of a method will cause a failure!"); + this.options = options; } private final Map counters = new HashMap<>(); @@ -68,16 +69,16 @@ class CompilationCounters { Integer val = counters.get(method); val = val != null ? val + 1 : 1; counters.put(method, val); - if (val > Options.CompilationCountLimit.getValue()) { + if (val > Options.CompilationCountLimit.getValue(options)) { TTY.printf("Error. Method %s was compiled too many times. Number of compilations: %d\n", fmt(method), - CompilationCounters.Options.CompilationCountLimit.getValue()); + CompilationCounters.Options.CompilationCountLimit.getValue(options)); TTY.println("==================================== High compilation counters ===================================="); SortedSet> sortedCounters = new TreeSet<>(new CounterComparator()); for (Map.Entry e : counters.entrySet()) { sortedCounters.add(e); } for (Map.Entry entry : sortedCounters) { - if (entry.getValue() >= Options.CompilationCountLimit.getValue() / 2) { + if (entry.getValue() >= Options.CompilationCountLimit.getValue(options) / 2) { TTY.out.printf("%d\t%s%n", entry.getValue(), str(entry.getKey())); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java index a40d0711aaf..ab4fdb18be8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java @@ -44,8 +44,8 @@ import java.util.concurrent.ConcurrentLinkedDeque; import org.graalvm.compiler.debug.CSVUtil; import org.graalvm.compiler.debug.Management; import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionValue; -import com.sun.management.ThreadMXBean; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotInstalledCode; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; @@ -56,12 +56,11 @@ public final class CompilationStatistics { public static class Options { // @formatter:off @Option(help = "Enables CompilationStatistics.") - public static final OptionValue UseCompilationStatistics = new OptionValue<>(false); + public static final OptionKey UseCompilationStatistics = new OptionKey<>(false); // @formatter:on } private static final long RESOLUTION = 100000000; - private static final boolean ENABLED = Options.UseCompilationStatistics.getValue(); private static final CompilationStatistics DUMMY = new CompilationStatistics(null, false); @@ -88,7 +87,7 @@ public final class CompilationStatistics { private static long zeroTime = System.nanoTime(); private static long getThreadAllocatedBytes() { - ThreadMXBean thread = (ThreadMXBean) Management.getThreadMXBean(); + com.sun.management.ThreadMXBean thread = (com.sun.management.ThreadMXBean) Management.getThreadMXBean(); return thread.getThreadAllocatedBytes(currentThread().getId()); } @@ -114,6 +113,7 @@ public final class CompilationStatistics { bytecodeCount = method.getCodeSize(); threadAllocatedBytesStart = getThreadAllocatedBytes(); } else { + assert DUMMY == null : "only DUMMY has no method"; holder = ""; name = ""; signature = ""; @@ -122,7 +122,7 @@ public final class CompilationStatistics { } public void finish(HotSpotResolvedJavaMethod method, HotSpotInstalledCode code) { - if (ENABLED) { + if (isEnabled()) { duration = System.nanoTime() - startTime; codeSize = (int) code.getCodeSize(); memoryUsed = getThreadAllocatedBytes() - threadAllocatedBytesStart; @@ -137,8 +137,8 @@ public final class CompilationStatistics { return current.get().isEmpty() ? null : current.get().getLast(); } - public static CompilationStatistics create(HotSpotResolvedJavaMethod method, boolean isOSR) { - if (ENABLED) { + public static CompilationStatistics create(OptionValues options, HotSpotResolvedJavaMethod method, boolean isOSR) { + if (Options.UseCompilationStatistics.getValue(options)) { CompilationStatistics stats = new CompilationStatistics(method, isOSR); list.add(stats); current.get().addLast(stats); @@ -148,11 +148,12 @@ public final class CompilationStatistics { } } + public boolean isEnabled() { + return this != DUMMY; + } + @SuppressWarnings("deprecation") public static void clear(String dumpName) { - if (!ENABLED) { - return; - } try { ConcurrentLinkedDeque snapshot = list; long snapshotZeroTime = zeroTime; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java index e86a1bdb71c..42377130b1c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java @@ -22,50 +22,46 @@ */ package org.graalvm.compiler.hotspot; -import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnBailout; -import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException; -import static org.graalvm.compiler.core.GraalCompilerOptions.PrintAfterCompilation; -import static org.graalvm.compiler.core.GraalCompilerOptions.PrintBailout; -import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation; -import static org.graalvm.compiler.core.GraalCompilerOptions.PrintFilter; -import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException; +import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM; +import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction; import static org.graalvm.compiler.core.phases.HighTier.Options.Inline; +import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; import java.util.List; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.core.CompilationPrinter; +import org.graalvm.compiler.core.CompilationWrapper; +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.debug.Assertions; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DebugDumpScope; -import org.graalvm.compiler.debug.DebugTimer; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.debug.Management; -import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.TimeSource; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.debug.TimerKey; +import org.graalvm.compiler.options.EnumOptionKey; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.hotspot.EventProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; -import jdk.vm.ci.hotspot.HotSpotCompiledCode; import jdk.vm.ci.hotspot.HotSpotInstalledCode; +import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; import jdk.vm.ci.hotspot.HotSpotNmethod; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.runtime.JVMCICompiler; import jdk.vm.ci.services.JVMCIServiceLocator; -//JaCoCo Exclude - public class CompilationTask { - private static final DebugCounter BAILOUTS = Debug.counter("Bailouts"); - private static final EventProvider eventProvider; static { @@ -93,31 +89,147 @@ public class CompilationTask { private final boolean installAsDefault; private final boolean useProfilingInfo; + private final OptionValues options; - static class Lazy { - /** - * A {@link com.sun.management.ThreadMXBean} to be able to query some information about the - * current compiler thread, e.g. total allocated bytes. - */ - static final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean(); + final class HotSpotCompilationWrapper extends CompilationWrapper { + private final EventProvider.CompilationEvent compilationEvent; + CompilationResult result; + + HotSpotCompilationWrapper(EventProvider.CompilationEvent compilationEvent) { + super(compiler.getGraalRuntime().getOutputDirectory(), compiler.getGraalRuntime().getCompilationProblemsPerAction()); + this.compilationEvent = compilationEvent; + } + + @Override + protected DebugContext createRetryDebugContext(OptionValues retryOptions) { + SnippetReflectionProvider snippetReflection = compiler.getGraalRuntime().getHostProviders().getSnippetReflection(); + return DebugContext.create(retryOptions, new GraalDebugHandlersFactory(snippetReflection)); + } + + @Override + public String toString() { + return getMethod().format("%H.%n(%p)"); + } + + @Override + protected HotSpotCompilationRequestResult handleException(Throwable t) { + if (t instanceof BailoutException) { + BailoutException bailout = (BailoutException) t; + /* + * Handling of permanent bailouts: Permanent bailouts that can happen for example + * due to unsupported unstructured control flow in the bytecodes of a method must + * not be retried. Hotspot compile broker will ensure that no recompilation at the + * given tier will happen if retry is false. + */ + return HotSpotCompilationRequestResult.failure(bailout.getMessage(), !bailout.isPermanent()); + } + // Log a failure event. + EventProvider.CompilerFailureEvent event = eventProvider.newCompilerFailureEvent(); + if (event.shouldWrite()) { + event.setCompileId(getId()); + event.setMessage(t.getMessage()); + event.commit(); + } + + /* + * Treat random exceptions from the compiler as indicating a problem compiling this + * method. Report the result of toString instead of getMessage to ensure that the + * exception type is included in the output in case there's no detail mesage. + */ + return HotSpotCompilationRequestResult.failure(t.toString(), false); + } + + @Override + protected ExceptionAction lookupAction(OptionValues values, EnumOptionKey actionKey) { + /* + * Automatically exit VM on non-bailout during bootstrap or when asserts are enabled but + * respect CompilationFailureAction if it has been explicitly set. + */ + if (actionKey == CompilationFailureAction && !actionKey.hasBeenSet(values)) { + if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) { + return ExitVM; + } + } + return super.lookupAction(values, actionKey); + } + + @SuppressWarnings("try") + @Override + protected HotSpotCompilationRequestResult performCompilation(DebugContext debug) { + HotSpotResolvedJavaMethod method = getMethod(); + int entryBCI = getEntryBCI(); + final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; + CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR); + + final CompilationPrinter printer = CompilationPrinter.begin(options, compilationId, method, entryBCI); + + try (DebugContext.Scope s = debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { + // Begin the compilation event. + compilationEvent.begin(); + result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options, debug); + } catch (Throwable e) { + throw debug.handle(e); + } finally { + // End the compilation event. + compilationEvent.end(); + } + + if (result != null) { + try (DebugCloseable b = CodeInstallationTime.start(debug)) { + installMethod(debug, result); + } + // Installation is included in compilation time and memory usage reported by printer + printer.finish(result); + } + stats.finish(method, installedCode); + if (result != null) { + return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize()); + } + return null; + } } - public CompilationTask(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault) { + public CompilationTask(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault, + OptionValues options) { this.jvmciRuntime = jvmciRuntime; this.compiler = compiler; this.compilationId = new HotSpotCompilationIdentifier(request); this.useProfilingInfo = useProfilingInfo; this.installAsDefault = installAsDefault; + + /* + * Disable inlining if HotSpot has it disabled unless it's been explicitly set in Graal. + */ + HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime(); + GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); + OptionValues newOptions = options; + if (!config.inline) { + EconomicMap, Object> m = OptionValues.newOptionMap(); + if (Inline.getValue(options) && !Inline.hasBeenSet(options)) { + m.put(Inline, false); + } + if (InlineDuringParsing.getValue(options) && !InlineDuringParsing.hasBeenSet(options)) { + m.put(InlineDuringParsing, false); + } + if (!m.isEmpty()) { + newOptions = new OptionValues(options, m); + } + } + this.options = newOptions; } public HotSpotResolvedJavaMethod getMethod() { return getRequest().getMethod(); } + CompilationIdentifier getCompilationIdentifier() { + return compilationId; + } + /** - * Returns the compilation id of this task. + * Returns the HotSpot id of this compilation. * - * @return compile id + * @return HotSpot compile id */ public int getId() { return getRequest().getId(); @@ -146,170 +258,75 @@ public class CompilationTask { /** * Time spent in compilation. */ - private static final DebugTimer CompilationTime = Debug.timer("CompilationTime"); + private static final TimerKey CompilationTime = DebugContext.timer("CompilationTime").doc("Time spent in compilation and code installation."); /** * Counts the number of compiled {@linkplain CompilationResult#getBytecodeSize() bytecodes}. */ - private static final DebugCounter CompiledBytecodes = Debug.counter("CompiledBytecodes"); + private static final CounterKey CompiledBytecodes = DebugContext.counter("CompiledBytecodes"); /** * Counts the number of compiled {@linkplain CompilationResult#getBytecodeSize() bytecodes} for * which {@linkplain CompilationResult#getTargetCode()} code was installed. */ - private static final DebugCounter CompiledAndInstalledBytecodes = Debug.counter("CompiledAndInstalledBytecodes"); + private static final CounterKey CompiledAndInstalledBytecodes = DebugContext.counter("CompiledAndInstalledBytecodes"); /** * Counts the number of installed {@linkplain CompilationResult#getTargetCodeSize()} bytes. */ - private static final DebugCounter InstalledCodeSize = Debug.counter("InstalledCodeSize"); + private static final CounterKey InstalledCodeSize = DebugContext.counter("InstalledCodeSize"); /** * Time spent in code installation. */ - public static final DebugTimer CodeInstallationTime = Debug.timer("CodeInstallation"); + public static final TimerKey CodeInstallationTime = DebugContext.timer("CodeInstallation"); + + public HotSpotCompilationRequestResult runCompilation() { + SnippetReflectionProvider snippetReflection = compiler.getGraalRuntime().getHostProviders().getSnippetReflection(); + try (DebugContext debug = DebugContext.create(options, new GraalDebugHandlersFactory(snippetReflection))) { + return runCompilation(debug); + } + } @SuppressWarnings("try") - public HotSpotCompilationRequestResult runCompilation() { + public HotSpotCompilationRequestResult runCompilation(DebugContext debug) { HotSpotGraalRuntimeProvider graalRuntime = compiler.getGraalRuntime(); GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); - final long threadId = Thread.currentThread().getId(); int entryBCI = getEntryBCI(); - final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; + boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; HotSpotResolvedJavaMethod method = getMethod(); - // register the compilation id in the method metrics - if (Debug.isMethodMeterEnabled()) { - if (getEntryBCI() != JVMCICompiler.INVOCATION_ENTRY_BCI) { - Debug.methodMetrics(method).addToMetric(getId(), "CompilationIdOSR"); - } else { - Debug.methodMetrics(method).addToMetric(getId(), "CompilationId"); - } - } - // Log a compilation event. EventProvider.CompilationEvent compilationEvent = eventProvider.newCompilationEvent(); - // If there is already compiled code for this method on our level we simply return. - // JVMCI compiles are always at the highest compile level, even in non-tiered mode so we - // only need to check for that value. - if (method.hasCodeAtLevel(entryBCI, config.compilationLevelFullOptimization)) { - return null; + if (installAsDefault) { + // If there is already compiled code for this method on our level we simply return. + // JVMCI compiles are always at the highest compile level, even in non-tiered mode so we + // only need to check for that value. + if (method.hasCodeAtLevel(entryBCI, config.compilationLevelFullOptimization)) { + return HotSpotCompilationRequestResult.failure("Already compiled", false); + } + if (HotSpotGraalCompilerFactory.checkGraalCompileOnlyFilter(method.getDeclaringClass().toJavaName(), method.getName(), method.getSignature().toString(), + HotSpotJVMCICompilerFactory.CompilationLevel.FullOptimization) != HotSpotJVMCICompilerFactory.CompilationLevel.FullOptimization) { + return HotSpotCompilationRequestResult.failure("GraalCompileOnly excluded", false); + } } - CompilationResult result = null; - try (DebugCloseable a = CompilationTime.start()) { - CompilationStatistics stats = CompilationStatistics.create(method, isOSR); - final boolean printCompilation = PrintCompilation.getValue() && !TTY.isSuppressed(); - final boolean printAfterCompilation = PrintAfterCompilation.getValue() && !TTY.isSuppressed(); - if (printCompilation) { - TTY.println(getMethodDescription() + "..."); - } - - TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(), method); - final long start; - final long allocatedBytesBefore; - if (printAfterCompilation || printCompilation) { - start = TimeSource.getTimeNS(); - allocatedBytesBefore = printAfterCompilation || printCompilation ? Lazy.threadMXBean.getThreadAllocatedBytes(threadId) : 0L; - } else { - start = 0L; - allocatedBytesBefore = 0L; - } - - try (Scope s = Debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { - // Begin the compilation event. - compilationEvent.begin(); - /* - * Disable inlining if HotSpot has it disabled unless it's been explicitly set in - * Graal. - */ - boolean disableInlining = !config.inline && !Inline.hasBeenSet(); - try (OverrideScope s1 = disableInlining ? OptionValue.override(Inline, false) : null) { - result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId); - } - } catch (Throwable e) { - throw Debug.handle(e); - } finally { - // End the compilation event. - compilationEvent.end(); - - filter.remove(); - - if (printAfterCompilation || printCompilation) { - final long stop = TimeSource.getTimeNS(); - final long duration = (stop - start) / 1000000; - final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1; - final int bytecodeSize = result != null ? result.getBytecodeSize() : 0; - final long allocatedBytesAfter = Lazy.threadMXBean.getThreadAllocatedBytes(threadId); - final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024; - - if (printAfterCompilation) { - TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); - } else if (printCompilation) { - TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dB %5dkB", getId(), "", "", "", duration, bytecodeSize, targetCodeSize, allocatedKBytes)); - } - } - } - - if (result != null) { - try (DebugCloseable b = CodeInstallationTime.start()) { - installMethod(result); - } - } - stats.finish(method, installedCode); - if (result != null) { - return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize()); - } - return null; - } catch (BailoutException bailout) { - BAILOUTS.increment(); - if (ExitVMOnBailout.getValue()) { - TTY.out.println(method.format("Bailout in %H.%n(%p)")); - bailout.printStackTrace(TTY.out); - System.exit(-1); - } else if (PrintBailout.getValue()) { - TTY.out.println(method.format("Bailout in %H.%n(%p)")); - bailout.printStackTrace(TTY.out); - } - /* - * Handling of permanent bailouts: Permanent bailouts that can happen for example due to - * unsupported unstructured control flow in the bytecodes of a method must not be - * retried. Hotspot compile broker will ensure that no recompilation at the given tier - * will happen if retry is false. - */ - final boolean permanentBailout = bailout.isPermanent(); - if (permanentBailout && PrintBailout.getValue()) { - TTY.println("Permanent bailout %s compiling method %s %s.", bailout.getMessage(), HotSpotGraalCompiler.str(method), (isOSR ? "OSR" : "")); - } - return HotSpotCompilationRequestResult.failure(bailout.getMessage(), !permanentBailout); - } catch (Throwable t) { - // Log a failure event. - EventProvider.CompilerFailureEvent event = eventProvider.newCompilerFailureEvent(); - if (event.shouldWrite()) { - event.setCompileId(getId()); - event.setMessage(t.getMessage()); - event.commit(); - } - - handleException(t); - /* - * Treat random exceptions from the compiler as indicating a problem compiling this - * method. Report the result of toString instead of getMessage to ensure that the - * exception type is included in the output in case there's no detail mesage. - */ - return HotSpotCompilationRequestResult.failure(t.toString(), false); + HotSpotCompilationWrapper compilation = new HotSpotCompilationWrapper(compilationEvent); + try (DebugCloseable a = CompilationTime.start(debug)) { + return compilation.run(debug); } finally { try { int compiledBytecodes = 0; int codeSize = 0; - if (result != null) { - compiledBytecodes = result.getBytecodeSize(); - CompiledBytecodes.add(compiledBytecodes); + + if (compilation.result != null) { + compiledBytecodes = compilation.result.getBytecodeSize(); + CompiledBytecodes.add(debug, compiledBytecodes); if (installedCode != null) { codeSize = installedCode.getSize(); - CompiledAndInstalledBytecodes.add(compiledBytecodes); - InstalledCodeSize.add(codeSize); + CompiledAndInstalledBytecodes.add(debug, compiledBytecodes); + InstalledCodeSize.add(debug, codeSize); } } @@ -318,63 +335,29 @@ public class CompilationTask { compilationEvent.setMethod(method.format("%H.%n(%p)")); compilationEvent.setCompileId(getId()); compilationEvent.setCompileLevel(config.compilationLevelFullOptimization); - compilationEvent.setSucceeded(result != null && installedCode != null); + compilationEvent.setSucceeded(compilation.result != null && installedCode != null); compilationEvent.setIsOsr(isOSR); compilationEvent.setCodeSize(codeSize); compilationEvent.setInlinedBytes(compiledBytecodes); compilationEvent.commit(); } } catch (Throwable t) { - handleException(t); + return compilation.handleException(t); } } } - protected void handleException(Throwable t) { - /* - * Automatically enable ExitVMOnException during bootstrap or when asserts are enabled but - * respect ExitVMOnException if it's been explicitly set. - */ - boolean exitVMOnException = ExitVMOnException.getValue(); - if (!ExitVMOnException.hasBeenSet()) { - assert (exitVMOnException = true) == true; - if (!exitVMOnException) { - HotSpotGraalRuntimeProvider runtime = compiler.getGraalRuntime(); - if (runtime.isBootstrapping()) { - exitVMOnException = true; - } - } - } - - if (PrintStackTraceOnException.getValue() || exitVMOnException) { - try { - t.printStackTrace(TTY.out); - } catch (Throwable throwable) { - // Don't let an exception here change the other control flow - } - } - - if (exitVMOnException) { - System.exit(-1); - } - } - - private String getMethodDescription() { - HotSpotResolvedJavaMethod method = getMethod(); - return String.format("%-6d JVMCI %-70s %-45s %-50s %s", getId(), method.getDeclaringClass().getName(), method.getName(), method.getSignature().toMethodDescriptor(), - getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + getEntryBCI() + ") "); - } - @SuppressWarnings("try") - private void installMethod(final CompilationResult compResult) { + private void installMethod(DebugContext debug, final CompilationResult compResult) { final CodeCacheProvider codeCache = jvmciRuntime.getHostJVMCIBackend().getCodeCache(); + HotSpotBackend backend = compiler.getGraalRuntime().getHostBackend(); installedCode = null; Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult}; - try (Scope s = Debug.scope("CodeInstall", context)) { - HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(getRequest().getMethod(), getRequest(), compResult); - installedCode = (HotSpotInstalledCode) codeCache.installCode(getRequest().getMethod(), compiledCode, null, getRequest().getMethod().getSpeculationLog(), installAsDefault); + try (DebugContext.Scope s = debug.scope("CodeInstall", context)) { + installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug, getRequest().getMethod(), getRequest(), compResult, + getRequest().getMethod().getSpeculationLog(), null, installAsDefault, context); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java index eb9532cdccb..14a95d28592 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java @@ -28,8 +28,9 @@ import java.util.Arrays; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -53,12 +54,12 @@ class CompilationWatchDog extends Thread implements AutoCloseable { public static class Options { // @formatter:off @Option(help = "Delay in seconds before watch dog monitoring a compilation (0 disables monitoring).", type = OptionType.Debug) - public static final OptionValue CompilationWatchDogStartDelay = new OptionValue<>(30.0D); + public static final OptionKey CompilationWatchDogStartDelay = new OptionKey<>(0.0D); @Option(help = "Interval in seconds between a watch dog reporting stack traces for long running compilations.", type = OptionType.Debug) - public static final OptionValue CompilationWatchDogStackTraceInterval = new OptionValue<>(30.0D); + public static final OptionKey CompilationWatchDogStackTraceInterval = new OptionKey<>(60.0D); @Option(help = "Number of contiguous identical compiler thread stack traces allowed before the VM exits " + "on the basis of a stuck compilation.", type = OptionType.Debug) - public static final OptionValue NonFatalIdenticalCompilationSnapshots = new OptionValue<>(10); + public static final OptionKey NonFatalIdenticalCompilationSnapshots = new OptionKey<>(20); // @formatter:on } @@ -90,12 +91,12 @@ class CompilationWatchDog extends Thread implements AutoCloseable { * this time period and thus not be actively monitored by the watch dog. */ private static final int SPIN_TIMEOUT_MS = 1000; - private static final long START_DELAY_MS = ms(Options.CompilationWatchDogStartDelay.getValue()); - private static final long STACK_TRACE_INTERVAL_MS = ms(Options.CompilationWatchDogStackTraceInterval.getValue()); - private static final boolean ENABLED = START_DELAY_MS > 0.0D; private WatchDogState state = WatchDogState.SLEEPING; private final Thread compilerThread; + private final long startDelayMilliseconds; + private final long stackTraceIntervalMilliseconds; + private final int nonFatalIdenticalCompilationSnapshots; private volatile ResolvedJavaMethod currentMethod; private volatile int currentId; private ResolvedJavaMethod lastWatched; @@ -106,11 +107,14 @@ class CompilationWatchDog extends Thread implements AutoCloseable { private int numberOfIdenticalStackTraces; private StackTraceElement[] lastStackTrace; - CompilationWatchDog(Thread compilerThread) { + CompilationWatchDog(Thread compilerThread, long startDelayMilliseconds, long stackTraceIntervalMilliseconds, int nonFatalIdenticalCompilationSnapshots) { this.compilerThread = compilerThread; this.setName("WatchDog" + getId() + "[" + compilerThread.getName() + "]"); this.setPriority(Thread.MAX_PRIORITY); this.setDaemon(true); + this.startDelayMilliseconds = startDelayMilliseconds; + this.stackTraceIntervalMilliseconds = stackTraceIntervalMilliseconds; + this.nonFatalIdenticalCompilationSnapshots = nonFatalIdenticalCompilationSnapshots; } public void startCompilation(ResolvedJavaMethod method, int id) { @@ -183,8 +187,8 @@ class CompilationWatchDog extends Thread implements AutoCloseable { @Override public void run() { - trace("Started%n", this); try { + trace("Started%n", this); while (true) { // get a copy of the last set method final ResolvedJavaMethod currentlyCompiling = currentMethod; @@ -200,25 +204,27 @@ class CompilationWatchDog extends Thread implements AutoCloseable { tick(WatchDogState.WATCHING_WITHOUT_STACK_INSPECTION); break; case WATCHING_WITHOUT_STACK_INSPECTION: - if (currentlyCompiling == lastWatched) { - if (elapsed >= START_DELAY_MS) { + if (currentlyCompiling.equals(lastWatched)) { + if (elapsed >= startDelayMilliseconds) { // we looked at the same compilation for a certain time // so now we start to collect stack traces tick(WatchDogState.WATCHING_WITH_STACK_INSPECTION); trace("changes mode to watching with stack traces"); } else { - // we still compile the same method but won't collect traces yet + // we still compile the same method but won't collect traces + // yet trace("watching without stack traces [%.2f seconds]", secs(elapsed)); } elapsed += SPIN_TIMEOUT_MS; } else { - // compilation finished before we exceeded initial watching period + // compilation finished before we exceeded initial watching + // period reset(); } break; case WATCHING_WITH_STACK_INSPECTION: - if (currentlyCompiling == lastWatched) { - if (elapsed >= START_DELAY_MS + (traceIntervals * STACK_TRACE_INTERVAL_MS)) { + if (currentlyCompiling.equals(lastWatched)) { + if (elapsed >= startDelayMilliseconds + (traceIntervals * stackTraceIntervalMilliseconds)) { trace("took a stack trace"); boolean newStackTrace = recordStackTrace(compilerThread.getStackTrace()); if (!newStackTrace) { @@ -226,7 +232,7 @@ class CompilationWatchDog extends Thread implements AutoCloseable { numberOfIdenticalStackTraces = 0; } numberOfIdenticalStackTraces++; - if (numberOfIdenticalStackTraces > Options.NonFatalIdenticalCompilationSnapshots.getValue()) { + if (numberOfIdenticalStackTraces > nonFatalIdenticalCompilationSnapshots) { synchronized (CompilationWatchDog.class) { TTY.printf("======================= WATCH DOG THREAD =======================%n" + "%s took %d identical stack traces, which indicates a stuck compilation (id=%d) of %s%n%sExiting VM%n", this, @@ -247,7 +253,8 @@ class CompilationWatchDog extends Thread implements AutoCloseable { } elapsed += SPIN_TIMEOUT_MS; } else { - // compilation finished before we are able to collect stack traces + // compilation finished before we are able to collect stack + // traces reset(); } break; @@ -255,16 +262,29 @@ class CompilationWatchDog extends Thread implements AutoCloseable { break; } } - Thread.sleep(SPIN_TIMEOUT_MS); + try { + Thread.sleep(SPIN_TIMEOUT_MS); + } catch (InterruptedException e) { + // Silently swallow + } } + } catch (VirtualMachineError vmError) { + /* + * We encounter a VM error. This includes for example OutOfMemoryExceptions. In such a + * case we silently swallow the error. If it happens again the application thread will + * most likely encounter the same problem. If not the watchdog thread will no longer + * monitor the compilation and thus the error cannot happen again. + */ } catch (Throwable t) { - synchronized (CompilationWatchDog.class) { - TTY.printf("%s encountered an exception%n%s%n", this, fmt(t)); - } + /* + * A real exception happened on the compilation watchdog. This is unintended behavior + * and must not happen in any case. + */ + throw new InternalError(String.format("%s encountered an exception%n%s%n", this, fmt(t)), t); } } - private static final ThreadLocal WATCH_DOGS = ENABLED ? new ThreadLocal<>() : null; + private static final ThreadLocal WATCH_DOGS = new ThreadLocal<>(); /** * Opens a scope for watching the compilation of a given method. @@ -276,13 +296,16 @@ class CompilationWatchDog extends Thread implements AutoCloseable { * is the whole compilation so that leaving the scope will cause {@link #close()} to be * called. */ - static CompilationWatchDog watch(ResolvedJavaMethod method, int id) { - if (ENABLED) { + static CompilationWatchDog watch(ResolvedJavaMethod method, int id, OptionValues options) { + long startDelayMilliseconds = ms(Options.CompilationWatchDogStartDelay.getValue(options)); + if (startDelayMilliseconds > 0.0D) { // Lazily get a watch dog thread for the current compiler thread CompilationWatchDog watchDog = WATCH_DOGS.get(); if (watchDog == null) { Thread currentThread = currentThread(); - watchDog = new CompilationWatchDog(currentThread); + long stackTraceIntervalMilliseconds = ms(Options.CompilationWatchDogStackTraceInterval.getValue(options)); + int nonFatalIdenticalCompilationSnapshots = Options.NonFatalIdenticalCompilationSnapshots.getValue(options); + watchDog = new CompilationWatchDog(currentThread, startDelayMilliseconds, stackTraceIntervalMilliseconds, nonFatalIdenticalCompilationSnapshots); WATCH_DOGS.set(watchDog); watchDog.start(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorldOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorldOptions.java deleted file mode 100644 index 4f3032dc49f..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompileTheWorldOptions.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot; - -import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; - -/** - * Options related to {@link CompileTheWorld}. - * - * Note: This must be a top level class to work around for - * Eclipse bug 477597. - */ -public class CompileTheWorldOptions { - // @formatter:off - @Option(help = "Class path denoting methods to compile", type = OptionType.Debug) - public static final OptionValue CompileTheWorldClasspath = new OptionValue<>(CompileTheWorld.SUN_BOOT_CLASS_PATH); - @Option(help = "Verbose CompileTheWorld operation", type = OptionType.Debug) - public static final OptionValue CompileTheWorldVerbose = new OptionValue<>(true); - @Option(help = "The number of CompileTheWorld iterations to perform", type = OptionType.Debug) - public static final OptionValue CompileTheWorldIterations = new OptionValue<>(1); - @Option(help = "Only compile methods matching this filter", type = OptionType.Debug) - public static final OptionValue CompileTheWorldMethodFilter = new OptionValue<>(null); - @Option(help = "Exclude methods matching this filter from compilation", type = OptionType.Debug) - public static final OptionValue CompileTheWorldExcludeMethodFilter = new OptionValue<>(null); - @Option(help = "First class to consider when using -XX:+CompileTheWorld", type = OptionType.Debug) - public static final OptionValue CompileTheWorldStartAt = new OptionValue<>(1); - @Option(help = "Last class to consider when using -XX:+CompileTheWorld", type = OptionType.Debug) - public static final OptionValue CompileTheWorldStopAt = new OptionValue<>(Integer.MAX_VALUE); - @Option(help = "Option value overrides to use during compile the world. For example, " + - "to disable inlining and partial escape analysis specify 'PartialEscapeAnalysis=false Inline=false'. " + - "The format for each option is the same as on the command line just without the '-Dgraal.' prefix.", type = OptionType.Debug) - public static final OptionValue CompileTheWorldConfig = new OptionValue<>(null); - - @Option(help = "Run CTW using as many threads as there are processors on the system", type = OptionType.Debug) - public static final OptionValue CompileTheWorldMultiThreaded = new OptionValue<>(false); - @Option(help = "Number of threads to use for multithreaded CTW. Defaults to Runtime.getRuntime().availableProcessors()", type = OptionType.Debug) - public static final OptionValue CompileTheWorldThreads = new OptionValue<>(0); - // @formatter:on - - /** - * Overrides {@link #CompileTheWorldStartAt} and {@link #CompileTheWorldStopAt} from {@code -XX} - * HotSpot options of the same name if the latter have non-default values. - */ - public static void overrideWithNativeOptions(GraalHotSpotVMConfig c) { - if (c.compileTheWorldStartAt != 1) { - CompileTheWorldStartAt.setValue(c.compileTheWorldStartAt); - } - if (c.compileTheWorldStopAt != Integer.MAX_VALUE) { - CompileTheWorldStopAt.setValue(c.compileTheWorldStopAt); - } - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java index 3940a9a7057..acc8f6292bb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java @@ -26,16 +26,18 @@ import static jdk.vm.ci.common.InitTimer.timer; import java.util.ArrayList; import java.util.Collections; -import java.util.IdentityHashMap; import java.util.List; import java.util.stream.Collectors; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.serviceprovider.GraalServices; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.common.InitTimer; @@ -52,7 +54,7 @@ public abstract class CompilerConfigurationFactory implements Comparable CompilerConfiguration = new OptionValue<>(null); + public static final OptionKey CompilerConfiguration = new OptionKey<>(null); // @formatter:on } @@ -91,7 +93,7 @@ public abstract class CompilerConfigurationFactory implements Comparable, HotSpotBackendFactory> backends = new IdentityHashMap<>(); + private final EconomicMap, HotSpotBackendFactory> backends = EconomicMap.create(); @SuppressWarnings("try") public DefaultBackendMap(String backendName) { @@ -124,18 +126,11 @@ public abstract class CompilerConfigurationFactory implements Comparable factories = assertionsEnabled() ? new ArrayList<>() : null; + private static final List factories = Assertions.assertionsEnabled() ? new ArrayList<>() : null; private static boolean checkAndAddNewFactory(CompilerConfigurationFactory factory) { for (CompilerConfigurationFactory other : factories) { @@ -169,10 +164,10 @@ public abstract class CompilerConfigurationFactory implements Comparable*"); - public final int classMirrorOffset = getFieldOffset("Klass::_java_mirror", Integer.class, "oop"); + public final boolean classMirrorIsHandle; + public final int classMirrorOffset; + { + String name = "Klass::_java_mirror"; + int offset = -1; + boolean isHandle = false; + try { + offset = getFieldOffset(name, Integer.class, "oop"); + } catch (JVMCIError e) { + + } + if (offset == -1) { + try { + offset = getFieldOffset(name, Integer.class, "jobject"); + isHandle = true; + } catch (JVMCIError e) { + + } + } + if (offset == -1) { + throw new JVMCIError("cannot get offset of field " + name + " with type oop or jobject"); + } + classMirrorOffset = offset; + classMirrorIsHandle = isHandle; + } public final int klassSuperKlassOffset = getFieldOffset("Klass::_super", Integer.class, "Klass*"); public final int klassModifierFlagsOffset = getFieldOffset("Klass::_modifier_flags", Integer.class, "jint"); @@ -437,8 +463,15 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess { public final long markOopDescHashMaskInPlace = getConstant("markOopDesc::hash_mask_in_place", Long.class); public final int unlockedMask = getConstant("markOopDesc::unlocked_value", Integer.class); + public final int monitorMask = getConstant("markOopDesc::monitor_value", Integer.class, -1); public final int biasedLockPattern = getConstant("markOopDesc::biased_lock_pattern", Integer.class); + // This field has no type in vmStructs.cpp + public final int objectMonitorOwner = getFieldOffset("ObjectMonitor::_owner", Integer.class, null, -1); + public final int objectMonitorRecursions = getFieldOffset("ObjectMonitor::_recursions", Integer.class, "intptr_t", -1); + public final int objectMonitorCxq = getFieldOffset("ObjectMonitor::_cxq", Integer.class, "ObjectWaiter*", -1); + public final int objectMonitorEntryList = getFieldOffset("ObjectMonitor::_EntryList", Integer.class, "ObjectWaiter*", -1); + public final int markWordNoHashInPlace = getConstant("markOopDesc::no_hash_in_place", Integer.class); public final int markWordNoLockInPlace = getConstant("markOopDesc::no_lock_in_place", Integer.class); @@ -637,17 +670,17 @@ public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess { public final long sha256ImplCompressMB = getFieldValue("StubRoutines::_sha256_implCompressMB", Long.class, "address", 0L); public final long sha512ImplCompress = getFieldValue("StubRoutines::_sha512_implCompress", Long.class, "address", 0L); public final long sha512ImplCompressMB = getFieldValue("StubRoutines::_sha512_implCompressMB", Long.class, "address", 0L); - public final long multiplyToLen = getFieldValue("StubRoutines::_multiplyToLen", Long.class, "address", 0L); + public final long multiplyToLen = getFieldValue("StubRoutines::_multiplyToLen", Long.class, "address", longRequiredOnAMD64); public final long counterModeAESCrypt = getFieldValue("StubRoutines::_counterMode_AESCrypt", Long.class, "address", 0L); public final long ghashProcessBlocks = getFieldValue("StubRoutines::_ghash_processBlocks", Long.class, "address", 0L); public final long crc32cTableTddr = getFieldValue("StubRoutines::_crc32c_table_addr", Long.class, "address", 0L); public final long updateBytesCRC32C = getFieldValue("StubRoutines::_updateBytesCRC32C", Long.class, "address", 0L); public final long updateBytesAdler32 = getFieldValue("StubRoutines::_updateBytesAdler32", Long.class, "address", 0L); - public final long squareToLen = getFieldValue("StubRoutines::_squareToLen", Long.class, "address", 0L); - public final long mulAdd = getFieldValue("StubRoutines::_mulAdd", Long.class, "address", 0L); - public final long montgomeryMultiply = getFieldValue("StubRoutines::_montgomeryMultiply", Long.class, "address", 0L); - public final long montgomerySquare = getFieldValue("StubRoutines::_montgomerySquare", Long.class, "address", 0L); + public final long squareToLen = getFieldValue("StubRoutines::_squareToLen", Long.class, "address", longRequiredOnAMD64); + public final long mulAdd = getFieldValue("StubRoutines::_mulAdd", Long.class, "address", longRequiredOnAMD64); + public final long montgomeryMultiply = getFieldValue("StubRoutines::_montgomeryMultiply", Long.class, "address", longRequiredOnAMD64); + public final long montgomerySquare = getFieldValue("StubRoutines::_montgomerySquare", Long.class, "address", longRequiredOnAMD64); public final long vectorizedMismatch = getFieldValue("StubRoutines::_vectorizedMismatch", Long.class, "address", 0L); public final long throwDelayedStackOverflowErrorEntry = getFieldValue("StubRoutines::_throw_delayed_StackOverflowError_entry", Long.class, "address", longNotPresentInJDK8); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java index 1e72687e1b3..440a70dcdf5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java @@ -22,12 +22,7 @@ */ package org.graalvm.compiler.hotspot; -import static org.graalvm.compiler.hotspot.stubs.StubUtil.newDescriptor; - import java.util.EnumSet; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.CompilationIdentifier; @@ -38,8 +33,6 @@ import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.DeoptimizationFetchUnrollInfoCallNode; -import org.graalvm.compiler.hotspot.nodes.UncommonTrapCallNode; import org.graalvm.compiler.hotspot.nodes.VMErrorNode; import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantStubCall; import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions; @@ -48,7 +41,6 @@ import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitution import org.graalvm.compiler.hotspot.replacements.SHA2Substitutions; import org.graalvm.compiler.hotspot.replacements.SHA5Substitutions; import org.graalvm.compiler.hotspot.replacements.SHASubstitutions; -import org.graalvm.compiler.hotspot.stubs.DeoptimizationStub; import org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub; @@ -67,15 +59,19 @@ import org.graalvm.compiler.lir.framemap.FrameMap; import org.graalvm.compiler.nodes.UnwindNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.SuitesProvider; -import org.graalvm.compiler.word.Pointer; import org.graalvm.compiler.word.Word; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.EconomicSet; +import org.graalvm.util.MapCursor; +import org.graalvm.word.Pointer; import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.code.CompiledCode; -import jdk.vm.ci.code.DebugInfo; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterSaveLayout; import jdk.vm.ci.code.StackSlot; @@ -94,13 +90,11 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen public static class Options { // @formatter:off - @Option(help = "Use Graal stubs instead of HotSpot stubs where possible") - public static final OptionValue PreferGraalStubs = new OptionValue<>(false); @Option(help = "Use Graal arithmetic stubs instead of HotSpot stubs where possible") - public static final OptionValue GraalArithmeticStubs = new OptionValue<>(true); + public static final OptionKey GraalArithmeticStubs = new OptionKey<>(true); @Option(help = "Enables instruction profiling on assembler level. Valid values are a comma separated list of supported instructions." + " Compare with subclasses of Assembler.InstructionCounter.", type = OptionType.Debug) - public static final OptionValue ASMInstructionProfiling = new OptionValue<>(null); + public static final OptionKey ASMInstructionProfiling = new OptionKey<>(null); // @formatter:on } @@ -134,16 +128,6 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen private final HotSpotGraalRuntimeProvider runtime; - /** - * @see DeoptimizationFetchUnrollInfoCallNode - */ - public static final ForeignCallDescriptor FETCH_UNROLL_INFO = new ForeignCallDescriptor("fetchUnrollInfo", Word.class, long.class, int.class); - - /** - * @see DeoptimizationStub#unpackFrames(ForeignCallDescriptor, Word, int) - */ - public static final ForeignCallDescriptor UNPACK_FRAMES = newDescriptor(DeoptimizationStub.class, "unpackFrames", int.class, Word.class, int.class); - /** * @see AESCryptSubstitutions#encryptBlockStub(ForeignCallDescriptor, Word, Word, Pointer) */ @@ -320,11 +304,6 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen public static final ForeignCallDescriptor INVOCATION_EVENT = new ForeignCallDescriptor("invocation_event", void.class, MethodCountersPointer.class); public static final ForeignCallDescriptor BACKEDGE_EVENT = new ForeignCallDescriptor("backedge_event", void.class, MethodCountersPointer.class, int.class, int.class); - /** - * @see UncommonTrapCallNode - */ - public static final ForeignCallDescriptor UNCOMMON_TRAP = new ForeignCallDescriptor("uncommonTrap", Word.class, Word.class, int.class, int.class); - public HotSpotBackend(HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) { super(providers); this.runtime = runtime; @@ -339,8 +318,9 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen * runtime} object was initialized and this backend was registered with it. * * @param jvmciRuntime + * @param options */ - public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime) { + public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options) { } /** @@ -349,8 +329,8 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen * @param lir the LIR to examine * @return the registers that are defined by or used as temps for any instruction in {@code lir} */ - protected final Set gatherDestroyedCallerRegisters(LIR lir) { - final Set destroyedRegisters = new HashSet<>(); + protected final EconomicSet gatherDestroyedCallerRegisters(LIR lir) { + final EconomicSet destroyedRegisters = EconomicSet.create(Equivalence.IDENTITY); ValueConsumer defConsumer = new ValueConsumer() { @Override @@ -382,7 +362,7 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen *

      * Any entry in {@code calleeSaveInfo} that {@linkplain SaveRegistersOp#supportsRemove() * supports} pruning will have {@code destroyedRegisters} - * {@linkplain SaveRegistersOp#remove(Set) removed} as these registers are declared as + * {@linkplain SaveRegistersOp#remove(EconomicSet) removed} as these registers are declared as * temporaries in the stub's {@linkplain ForeignCallLinkage linkage} (and thus will be saved by * the stub's caller). * @@ -393,17 +373,17 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen * @param frameMap used to {@linkplain FrameMap#offsetForStackSlot(StackSlot) convert} a virtual * slot to a frame slot index */ - protected void updateStub(Stub stub, Set destroyedRegisters, Map calleeSaveInfo, FrameMap frameMap) { + protected void updateStub(Stub stub, EconomicSet destroyedRegisters, EconomicMap calleeSaveInfo, FrameMap frameMap) { stub.initDestroyedCallerRegisters(destroyedRegisters); - for (Map.Entry e : calleeSaveInfo.entrySet()) { - SaveRegistersOp save = e.getValue(); + MapCursor cursor = calleeSaveInfo.getEntries(); + while (cursor.advance()) { + SaveRegistersOp save = cursor.getValue(); if (save.supportsRemove()) { save.remove(destroyedRegisters); } - DebugInfo info = e.getKey() == null ? null : e.getKey().debugInfo(); - if (info != null) { - info.setCalleeSaveInfo(save.getMap(frameMap)); + if (cursor.getKey() != LIRFrameState.NO_STATE) { + cursor.getKey().debugInfo().setCalleeSaveInfo(save.getMap(frameMap)); } } } @@ -419,7 +399,7 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen } protected void profileInstructions(LIR lir, CompilationResultBuilder crb) { - if (HotSpotBackend.Options.ASMInstructionProfiling.getValue() != null) { + if (HotSpotBackend.Options.ASMInstructionProfiling.getValue(lir.getOptions()) != null) { HotSpotInstructionProfiling.countInstructions(lir, crb.asm); } } @@ -427,7 +407,7 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen @Override public CompiledCode createCompiledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compResult) { HotSpotCompilationRequest compRequest = compilationRequest instanceof HotSpotCompilationRequest ? (HotSpotCompilationRequest) compilationRequest : null; - return HotSpotCompiledCodeBuilder.createCompiledCode(method, compRequest, compResult); + return HotSpotCompiledCodeBuilder.createCompiledCode(getCodeCache(), method, compRequest, compResult); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLowering.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCodeCacheListener.java similarity index 62% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLowering.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCodeCacheListener.java index 051b0443e40..8f8ea9e2ca5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLowering.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCodeCacheListener.java @@ -20,25 +20,21 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +package org.graalvm.compiler.hotspot; -package org.graalvm.compiler.core.aarch64; +import jdk.vm.ci.code.CompiledCode; +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.address.AddressNode; -import org.graalvm.compiler.phases.common.AddressLoweringPhase.AddressLowering; +public interface HotSpotCodeCacheListener { + /** + * Notifies this object on successful install into the CodeCache. + * + * @param codeCache the code cache into which the code was installed + * @param installedCode the code that was installed + * @param compiledCode the compiled code from which {@code installedCode} was produced + */ + default void notifyInstall(HotSpotCodeCacheProvider codeCache, InstalledCode installedCode, CompiledCode compiledCode) { -public class AArch64AddressLowering extends AddressLowering { - - @Override - public AddressNode lower(ValueNode address) { - return lower(address, null); } - - @Override - public AddressNode lower(ValueNode base, ValueNode offset) { - AArch64AddressNode ret = new AArch64AddressNode(base, offset); - // TODO improve - return base.graph().unique(ret); - } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java index 79c83799076..ecae5c3b699 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java @@ -42,6 +42,7 @@ import org.graalvm.compiler.code.DataSection; import org.graalvm.compiler.code.SourceMapping; import org.graalvm.compiler.graph.NodeSourcePosition; +import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.DebugInfo; import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.code.site.ConstantReference; @@ -61,13 +62,13 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class HotSpotCompiledCodeBuilder { - public static HotSpotCompiledCode createCompiledCode(ResolvedJavaMethod method, HotSpotCompilationRequest compRequest, CompilationResult compResult) { + public static HotSpotCompiledCode createCompiledCode(CodeCacheProvider codeCache, ResolvedJavaMethod method, HotSpotCompilationRequest compRequest, CompilationResult compResult) { String name = compResult.getName(); byte[] targetCode = compResult.getTargetCode(); int targetCodeSize = compResult.getTargetCodeSize(); - Site[] sites = getSortedSites(compResult); + Site[] sites = getSortedSites(codeCache, compResult); Assumption[] assumptions = compResult.getAssumptions(); @@ -201,7 +202,7 @@ public class HotSpotCompiledCodeBuilder { * {@code DebugInformationRecorder::add_new_pc_offset}). In addition, it expects * {@link Infopoint} PCs to be unique. */ - private static Site[] getSortedSites(CompilationResult target) { + private static Site[] getSortedSites(CodeCacheProvider codeCache, CompilationResult target) { List sites = new ArrayList<>( target.getExceptionHandlers().size() + target.getInfopoints().size() + target.getDataPatches().size() + target.getMarks().size() + target.getSourceMappings().size()); sites.addAll(target.getExceptionHandlers()); @@ -214,9 +215,11 @@ public class HotSpotCompiledCodeBuilder { * can really be represented and recording the end PC seems to give the best results and * corresponds with what C1 and C2 do. */ - for (SourceMapping source : target.getSourceMappings()) { - sites.add(new Infopoint(source.getEndOffset(), new DebugInfo(source.getSourcePosition()), InfopointReason.BYTECODE_POSITION)); - assert verifySourcePositionReceivers(source.getSourcePosition()); + if (codeCache.shouldDebugNonSafepoints()) { + for (SourceMapping source : target.getSourceMappings()) { + sites.add(new Infopoint(source.getEndOffset(), new DebugInfo(source.getSourcePosition()), InfopointReason.BYTECODE_POSITION)); + assert verifySourcePositionReceivers(source.getSourcePosition()); + } } SiteComparator c = new SiteComparator(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java index 794f7674037..82f3ca48652 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java @@ -27,15 +27,14 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static jdk.vm.ci.code.ValueUtil.isRegister; import java.util.Arrays; -import java.util.HashMap; - import org.graalvm.compiler.asm.Assembler; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.TargetDescription; @@ -102,7 +101,7 @@ public abstract class HotSpotCounterOp extends LIRInstruction { proc.apply(0, increments[0], displacement); } else { // Slow path with sort by displacements ascending int[] displacements = new int[names.length]; - HashMap offsetMap = new HashMap<>(names.length); + EconomicMap offsetMap = EconomicMap.create(); for (int i = 0; i < names.length; i++) { int arrayIndex = getIndex(names[i], groups[i], increments[i]); displacements[i] = getDisplacementForLongIndex(target, arrayIndex); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java index babe75eb3aa..0146727765c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotDebugInfoBuilder.java @@ -24,8 +24,14 @@ package org.graalvm.compiler.hotspot; import static jdk.vm.ci.code.BytecodeFrame.isPlaceholderBci; +import java.util.ArrayList; +import java.util.List; + +import org.graalvm.compiler.api.replacements.MethodSubstitution; +import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.core.gen.DebugInfoBuilder; -import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.GraalGraphError; +import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.ValueNode; @@ -36,6 +42,8 @@ import jdk.vm.ci.code.StackLockValue; import jdk.vm.ci.code.VirtualObject; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.meta.JavaValue; +import jdk.vm.ci.meta.MetaUtil; +import jdk.vm.ci.meta.ResolvedJavaMethod; /** * Extends {@link DebugInfoBuilder} to allocate the extra debug information required for locks. @@ -49,7 +57,7 @@ public class HotSpotDebugInfoBuilder extends DebugInfoBuilder { private HotSpotCodeCacheProvider codeCacheProvider; public HotSpotDebugInfoBuilder(NodeValueMap nodeValueMap, HotSpotLockStack lockStack, HotSpotLIRGenerator gen) { - super(nodeValueMap); + super(nodeValueMap, gen.getResult().getLIR().getDebug()); this.lockStack = lockStack; this.codeCacheProvider = gen.getProviders().getCodeCache(); } @@ -71,19 +79,48 @@ public class HotSpotDebugInfoBuilder extends DebugInfoBuilder { VirtualStackSlot slot = lockStack.makeLockSlot(lockDepth); ValueNode lock = state.lockAt(lockIndex); JavaValue object = toJavaValue(lock); - boolean eliminated = object instanceof VirtualObject || state.monitorIdAt(lockIndex) == null; - assert state.monitorIdAt(lockIndex) == null || state.monitorIdAt(lockIndex).getLockDepth() == lockDepth; + boolean eliminated = object instanceof VirtualObject || state.monitorIdAt(lockIndex).isEliminated(); + assert state.monitorIdAt(lockIndex).getLockDepth() == lockDepth; return new StackLockValue(object, slot, eliminated); } @Override protected BytecodeFrame computeFrameForState(FrameState state) { if (isPlaceholderBci(state.bci) && state.bci != BytecodeFrame.BEFORE_BCI) { - // This is really a hard error since an incorrect state could crash hotspot - throw GraalError.shouldNotReachHere("Invalid state " + BytecodeFrame.getPlaceholderBciName(state.bci) + " " + state); + raiseInvalidFrameStateError(state); } BytecodeFrame result = super.computeFrameForState(state); maxInterpreterFrameSize = Math.max(maxInterpreterFrameSize, codeCacheProvider.interpreterFrameSize(result)); return result; } + + protected void raiseInvalidFrameStateError(FrameState state) throws GraalGraphError { + // This is a hard error since an incorrect state could crash hotspot + NodeSourcePosition sourcePosition = state.getNodeSourcePosition(); + List context = new ArrayList<>(); + ResolvedJavaMethod replacementMethodWithProblematicSideEffect = null; + if (sourcePosition != null) { + NodeSourcePosition pos = sourcePosition; + while (pos != null) { + StringBuilder sb = new StringBuilder("parsing "); + ResolvedJavaMethod method = pos.getMethod(); + MetaUtil.appendLocation(sb, method, pos.getBCI()); + if (method.getAnnotation(MethodSubstitution.class) != null || + method.getAnnotation(Snippet.class) != null) { + replacementMethodWithProblematicSideEffect = method; + } + context.add(sb.toString()); + pos = pos.getCaller(); + } + } + String message = "Invalid frame state " + state; + if (replacementMethodWithProblematicSideEffect != null) { + message += " associated with a side effect in " + replacementMethodWithProblematicSideEffect.format("%H.%n(%p)") + " at a position that cannot be deoptimized to"; + } + GraalGraphError error = new GraalGraphError(message); + for (String c : context) { + error.addContext(c); + } + throw error; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java index 82d665be703..d316d0050bf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java @@ -24,10 +24,10 @@ package org.graalvm.compiler.hotspot; import jdk.vm.ci.meta.InvokeTarget; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.hotspot.stubs.Stub; +import org.graalvm.word.LocationIdentity; /** * The details required to link a HotSpot runtime or stub call. @@ -96,6 +96,11 @@ public interface HotSpotForeignCallLinkage extends ForeignCallLinkage, InvokeTar */ boolean isCompiledStub(); + /** + * Gets the stub, if any, this foreign call links to. + */ + Stub getStub(); + void finalizeAddress(Backend backend); long getAddress(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java index c4e0d8d6bad..ca00da23648 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java @@ -25,14 +25,13 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; -import java.util.Set; - -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.word.WordTypes; +import org.graalvm.util.EconomicSet; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.CallingConvention.Type; @@ -228,13 +227,24 @@ public class HotSpotForeignCallLinkageImpl extends HotSpotForeignCallTarget impl return address == 0L || stub != null; } + @Override + public Stub getStub() { + assert checkStubCondition(); + return stub; + } + + private boolean checkStubCondition() { + assert stub != null : "linkage without an address must be a stub - forgot to register a Stub associated with " + descriptor + "?"; + return true; + } + @Override public void finalizeAddress(Backend backend) { if (address == 0) { - assert stub != null : "linkage without an address must be a stub - forgot to register a Stub associated with " + descriptor + "?"; + assert checkStubCondition(); InstalledCode code = stub.getCode(backend); - Set destroyedRegisters = stub.getDestroyedCallerRegisters(); + EconomicSet destroyedRegisters = stub.getDestroyedCallerRegisters(); if (!destroyedRegisters.isEmpty()) { AllocatableValue[] temporaryLocations = new AllocatableValue[destroyedRegisters.size()]; int i = 0; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java index f4951022ed6..6c8455f6511 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java @@ -23,27 +23,25 @@ package org.graalvm.compiler.hotspot; import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions; -import static org.graalvm.compiler.nodes.StructuredGraph.NO_PROFILING_INFO; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.ROOT_COMPILATION; import java.io.ByteArrayOutputStream; import java.io.PrintStream; +import java.util.Collections; import java.util.Formattable; import java.util.Formatter; +import java.util.List; import org.graalvm.compiler.api.runtime.GraalJVMCICompiler; +import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.GraalCompiler; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.util.CompilationAlarm; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugConfigScope; -import org.graalvm.compiler.debug.DebugEnvironment; -import org.graalvm.compiler.debug.GraalDebugConfig; -import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.TopLevelDebugConfig; -import org.graalvm.compiler.debug.internal.DebugScope; -import org.graalvm.compiler.debug.internal.method.MethodMetricsRootScopeInfo; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Activation; +import org.graalvm.compiler.debug.DebugOptions; import org.graalvm.compiler.hotspot.CompilationCounters.Options; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.phases.OnStackReplacementPhase; @@ -56,15 +54,16 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.spi.Replacements; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.OptimisticOptimizations.Optimization; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.Suites; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.code.CompilationRequestResult; -import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; @@ -82,13 +81,21 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { private final HotSpotGraalRuntimeProvider graalRuntime; private final CompilationCounters compilationCounters; private final BootstrapWatchDog bootstrapWatchDog; + private List factories; - HotSpotGraalCompiler(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider graalRuntime) { + HotSpotGraalCompiler(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider graalRuntime, OptionValues options) { this.jvmciRuntime = jvmciRuntime; this.graalRuntime = graalRuntime; // It is sufficient to have one compilation counter object per Graal compiler object. - this.compilationCounters = Options.CompilationCountLimit.getValue() > 0 ? new CompilationCounters() : null; - this.bootstrapWatchDog = graalRuntime.isBootstrapping() && !GraalDebugConfig.Options.BootstrapInitializeOnly.getValue() ? BootstrapWatchDog.maybeCreate(graalRuntime) : null; + this.compilationCounters = Options.CompilationCountLimit.getValue(options) > 0 ? new CompilationCounters(options) : null; + this.bootstrapWatchDog = graalRuntime.isBootstrapping() && !DebugOptions.BootstrapInitializeOnly.getValue(options) ? BootstrapWatchDog.maybeCreate(graalRuntime) : null; + } + + public List getDebugHandlersFactories() { + if (factories == null) { + factories = Collections.singletonList(new GraalDebugHandlersFactory(graalRuntime.getHostProviders().getSnippetReflection())); + } + return factories; } @Override @@ -97,80 +104,89 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { } @Override - @SuppressWarnings("try") public CompilationRequestResult compileMethod(CompilationRequest request) { - if (graalRuntime.isBootstrapping() && GraalDebugConfig.Options.BootstrapInitializeOnly.getValue()) { - return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", GraalDebugConfig.Options.BootstrapInitializeOnly.getName()), true); + return compileMethod(request, true); + } + + @SuppressWarnings("try") + CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault) { + if (graalRuntime.isShutdown()) { + return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), false); } - if (bootstrapWatchDog != null && graalRuntime.isBootstrapping()) { - if (bootstrapWatchDog.hitCriticalCompilationRateOrTimeout()) { - // Drain the compilation queue to expedite completion of the bootstrap - return HotSpotCompilationRequestResult.failure("hit critical bootstrap compilation rate or timeout", true); + + ResolvedJavaMethod method = request.getMethod(); + OptionValues options = graalRuntime.getOptions(method); + + if (graalRuntime.isBootstrapping()) { + if (DebugOptions.BootstrapInitializeOnly.getValue(options)) { + return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", DebugOptions.BootstrapInitializeOnly.getName()), true); + } + if (bootstrapWatchDog != null) { + if (bootstrapWatchDog.hitCriticalCompilationRateOrTimeout()) { + // Drain the compilation queue to expedite completion of the bootstrap + return HotSpotCompilationRequestResult.failure("hit critical bootstrap compilation rate or timeout", true); + } } } - ResolvedJavaMethod method = request.getMethod(); HotSpotCompilationRequest hsRequest = (HotSpotCompilationRequest) request; - try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId()); + try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId(), options); BootstrapWatchDog.Watch w2 = bootstrapWatchDog == null ? null : bootstrapWatchDog.watch(request); - CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod();) { + CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(options);) { if (compilationCounters != null) { compilationCounters.countCompilation(method); } - // Ensure a debug configuration for this thread is initialized - if (Debug.isEnabled() && DebugScope.getConfig() == null) { - DebugEnvironment.initialize(TTY.out, graalRuntime.getHostProviders().getSnippetReflection()); - } - CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, true); + CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, installAsDefault, options); CompilationRequestResult r = null; - try (DebugConfigScope dcs = Debug.setConfig(new TopLevelDebugConfig()); - Debug.Scope s = Debug.methodMetricsScope("HotSpotGraalCompiler", MethodMetricsRootScopeInfo.create(method), true, method)) { - r = task.runCompilation(); + try (DebugContext debug = graalRuntime.openDebugContext(options, task.getCompilationIdentifier(), method, getDebugHandlersFactories()); + Activation a = debug.activate()) { + r = task.runCompilation(debug); } assert r != null; return r; } } - public void compileTheWorld() throws Throwable { - HotSpotCodeCacheProvider codeCache = (HotSpotCodeCacheProvider) jvmciRuntime.getHostJVMCIBackend().getCodeCache(); - int iterations = CompileTheWorldOptions.CompileTheWorldIterations.getValue(); - for (int i = 0; i < iterations; i++) { - codeCache.resetCompilationStatistics(); - TTY.println("CompileTheWorld : iteration " + i); - CompileTheWorld ctw = new CompileTheWorld(jvmciRuntime, this); - ctw.compile(); - } - System.exit(0); - } - - public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId) { + public StructuredGraph createGraph(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) { HotSpotBackend backend = graalRuntime.getHostBackend(); HotSpotProviders providers = backend.getProviders(); final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; - StructuredGraph graph = method.isNative() || isOSR ? null : getIntrinsicGraph(method, providers, compilationId); + StructuredGraph graph = method.isNative() || isOSR ? null : getIntrinsicGraph(method, providers, compilationId, options, debug); if (graph == null) { SpeculationLog speculationLog = method.getSpeculationLog(); if (speculationLog != null) { speculationLog.collectFailedSpeculations(); } - graph = new StructuredGraph(method, entryBCI, AllowAssumptions.from(OptAssumptions.getValue()), speculationLog, useProfilingInfo, compilationId); + graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.ifTrue(OptAssumptions.getValue(options))).method(method).entryBCI(entryBCI).speculationLog( + speculationLog).useProfilingInfo(useProfilingInfo).compilationId(compilationId).build(); } + return graph; + } - Suites suites = getSuites(providers); - LIRSuites lirSuites = getLIRSuites(providers); + public CompilationResult compileHelper(CompilationResultBuilderFactory crbf, CompilationResult result, StructuredGraph graph, ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, + OptionValues options) { + + HotSpotBackend backend = graalRuntime.getHostBackend(); + HotSpotProviders providers = backend.getProviders(); + final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; + + Suites suites = getSuites(providers, options); + LIRSuites lirSuites = getLIRSuites(providers, options); ProfilingInfo profilingInfo = useProfilingInfo ? method.getProfilingInfo(!isOSR, isOSR) : DefaultProfilingInfo.get(TriState.FALSE); - OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo); - if (isOSR) { - // In OSR compiles, we cannot rely on never executed code profiles, because - // all code after the OSR loop is never executed. + OptimisticOptimizations optimisticOpts = getOptimisticOpts(profilingInfo, options); + + /* + * Cut off never executed code profiles if there is code, e.g. after the osr loop, that is + * never executed. + */ + if (isOSR && !OnStackReplacementPhase.Options.DeoptAfterOSR.getValue(options)) { optimisticOpts.remove(Optimization.RemoveNeverExecutedCode); } - CompilationResult result = new CompilationResult(); + result.setEntryBCI(entryBCI); boolean shouldDebugNonSafepoints = providers.getCodeCache().shouldDebugNonSafepoints(); PhaseSuite graphBuilderSuite = configGraphBuilderSuite(providers.getSuites().getDefaultGraphBuilderSuite(), shouldDebugNonSafepoints, isOSR); - GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, result, CompilationResultBuilderFactory.Default); + GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, result, crbf); if (!isOSR && useProfilingInfo) { ProfilingInfo profile = profilingInfo; @@ -180,46 +196,55 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { return result; } + public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) { + StructuredGraph graph = createGraph(method, entryBCI, useProfilingInfo, compilationId, options, debug); + CompilationResult result = new CompilationResult(); + return compileHelper(CompilationResultBuilderFactory.Default, result, graph, method, entryBCI, useProfilingInfo, options); + } + /** * Gets a graph produced from the intrinsic for a given method that can be compiled and * installed for the method. * * @param method * @param compilationId + * @param options + * @param debug * @return an intrinsic graph that can be compiled and installed for {@code method} or null */ @SuppressWarnings("try") - public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, HotSpotProviders providers, CompilationIdentifier compilationId) { + public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, HotSpotProviders providers, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) { Replacements replacements = providers.getReplacements(); - ResolvedJavaMethod substMethod = replacements.getSubstitutionMethod(method); - if (substMethod != null) { + Bytecode subst = replacements.getSubstitutionBytecode(method); + if (subst != null) { + ResolvedJavaMethod substMethod = subst.getMethod(); assert !substMethod.equals(method); - StructuredGraph graph = new StructuredGraph(substMethod, AllowAssumptions.YES, NO_PROFILING_INFO, compilationId); - try (Debug.Scope scope = Debug.scope("GetIntrinsicGraph", graph)) { + StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).method(substMethod).compilationId(compilationId).build(); + try (DebugContext.Scope scope = debug.scope("GetIntrinsicGraph", graph)) { Plugins plugins = new Plugins(providers.getGraphBuilderPlugins()); GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); - IntrinsicContext initialReplacementContext = new IntrinsicContext(method, substMethod, replacements.getReplacementBytecodeProvider(), ROOT_COMPILATION); + IntrinsicContext initialReplacementContext = new IntrinsicContext(method, substMethod, subst.getOrigin(), ROOT_COMPILATION); new GraphBuilderPhase.Instance(providers.getMetaAccess(), providers.getStampProvider(), providers.getConstantReflection(), providers.getConstantFieldProvider(), config, OptimisticOptimizations.NONE, initialReplacementContext).apply(graph); assert !graph.isFrozen(); return graph; } catch (Throwable e) { - Debug.handle(e); + debug.handle(e); } } return null; } - protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo) { - return new OptimisticOptimizations(profilingInfo); + protected OptimisticOptimizations getOptimisticOpts(ProfilingInfo profilingInfo, OptionValues options) { + return new OptimisticOptimizations(profilingInfo, options); } - protected Suites getSuites(HotSpotProviders providers) { - return providers.getSuites().getDefaultSuites(); + protected Suites getSuites(HotSpotProviders providers, OptionValues options) { + return providers.getSuites().getDefaultSuites(options); } - protected LIRSuites getLIRSuites(HotSpotProviders providers) { - return providers.getSuites().getDefaultLIRSuites(); + protected LIRSuites getLIRSuites(HotSpotProviders providers, OptionValues options) { + return providers.getSuites().getDefaultLIRSuites(options); } /** @@ -245,6 +270,11 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler { newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); } if (isOSR) { + // We must not clear non liveness for OSR compilations. + GraphBuilderPhase graphBuilderPhase = (GraphBuilderPhase) newGbs.findPhase(GraphBuilderPhase.class).previous(); + GraphBuilderConfiguration graphBuilderConfig = graphBuilderPhase.getGraphBuilderConfig(); + GraphBuilderPhase newGraphBuilderPhase = new GraphBuilderPhase(graphBuilderConfig); + newGbs.findPhase(GraphBuilderPhase.class).set(newGraphBuilderPhase); newGbs.appendPhase(new OnStackReplacementPhase()); } return newGbs; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java index cab5141f0ad..b4b8e41890f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java @@ -23,23 +23,15 @@ package org.graalvm.compiler.hotspot; import static jdk.vm.ci.common.InitTimer.timer; -import static org.graalvm.compiler.options.OptionValue.PROFILE_OPTIONVALUE_PROPERTY_NAME; +import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; import java.io.PrintStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; -import java.util.ServiceLoader; import org.graalvm.compiler.debug.MethodFilter; import org.graalvm.compiler.options.Option; -import org.graalvm.compiler.options.OptionDescriptors; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.options.OptionsParser; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; @@ -48,35 +40,11 @@ import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotSignature; import jdk.vm.ci.runtime.JVMCIRuntime; -import jdk.vm.ci.services.Services; public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFactory { - /** - * The name of the system property specifying a file containing extra Graal option settings. - */ - private static final String GRAAL_OPTIONS_FILE_PROPERTY_NAME = "graal.options.file"; - - /** - * The name of the system property specifying the Graal version. - */ - private static final String GRAAL_VERSION_PROPERTY_NAME = "graal.version"; - - /** - * The prefix for system properties that correspond to {@link Option} annotated fields. A field - * named {@code MyOption} will have its value set from a system property with the name - * {@code GRAAL_OPTION_PROPERTY_PREFIX + "MyOption"}. - */ - public static final String GRAAL_OPTION_PROPERTY_PREFIX = "graal."; - private static MethodFilter[] graalCompileOnlyFilter; - - /** - * Gets the system property assignment that would set the current value for a given option. - */ - public static String asSystemPropertySetting(OptionValue value) { - return GRAAL_OPTION_PROPERTY_PREFIX + value.getName() + "=" + value.getValue(); - } + private static boolean compileGraalWithC1Only; private final HotSpotGraalJVMCIServiceLocator locator; @@ -89,125 +57,58 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto return "graal"; } + /** + * Initialized when this factory is {@linkplain #onSelection() selected}. + */ + private OptionValues options; + @Override public void onSelection() { - initializeOptions(); JVMCIVersionCheck.check(false); + assert options == null : "cannot select " + getClass() + " service more than once"; + options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS; + initializeGraalCompilePolicyFields(options); + /* + * Exercise this code path early to encourage loading now. This doesn't solve problem of + * deadlock during class loading but seems to eliminate it in practice. + */ + adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization); + adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple); + } + + private static void initializeGraalCompilePolicyFields(OptionValues options) { + compileGraalWithC1Only = Options.CompileGraalWithC1Only.getValue(options); + String optionValue = Options.GraalCompileOnly.getValue(options); + if (optionValue != null) { + MethodFilter[] filter = MethodFilter.parse(optionValue); + if (filter.length == 0) { + filter = null; + } + graalCompileOnlyFilter = filter; + } } @Override public void printProperties(PrintStream out) { - ServiceLoader loader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader()); out.println("[Graal properties]"); - OptionsParser.printFlags(loader, out, allOptionsSettings.keySet(), GRAAL_OPTION_PROPERTY_PREFIX); + options.printHelp(OptionsParser.getOptionsLoader(), out, GRAAL_OPTION_PROPERTY_PREFIX); } static class Options { // @formatter:off @Option(help = "In tiered mode compile Graal and JVMCI using optimized first tier code.", type = OptionType.Expert) - public static final OptionValue CompileGraalWithC1Only = new OptionValue<>(true); - - @Option(help = "Hook into VM-level mechanism for denoting compilations to be performed in first tier.", type = OptionType.Expert) - public static final OptionValue UseTrivialPrefixes = new OptionValue<>(false); + public static final OptionKey CompileGraalWithC1Only = new OptionKey<>(true); @Option(help = "A method filter selecting what should be compiled by Graal. All other requests will be reduced to CompilationLevel.Simple.", type = OptionType.Expert) - public static final OptionValue GraalCompileOnly = new OptionValue<>(null); + public static final OptionKey GraalCompileOnly = new OptionKey<>(null); // @formatter:on } - private static Map allOptionsSettings; - - /** - * Initializes options if they haven't already been initialized. - * - * Initialization means first parsing the options in the file denoted by the - * {@code VM.getSavedProperty(String) saved} system property named - * {@value HotSpotGraalCompilerFactory#GRAAL_OPTIONS_FILE_PROPERTY_NAME} if the file exists - * followed by parsing the options encoded in saved system properties whose names start with - * {@value #GRAAL_OPTION_PROPERTY_PREFIX}. Key/value pairs are parsed from the aforementioned - * file with {@link Properties#load(java.io.Reader)}. - */ - @SuppressWarnings("try") - private static synchronized void initializeOptions() { - if (allOptionsSettings == null) { - try (InitTimer t = timer("InitializeOptions")) { - ServiceLoader loader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader()); - Map savedProps = Services.getSavedProperties(); - String optionsFile = savedProps.get(GRAAL_OPTIONS_FILE_PROPERTY_NAME); - - if (optionsFile != null) { - File graalOptions = new File(optionsFile); - if (graalOptions.exists()) { - try (FileReader fr = new FileReader(graalOptions)) { - Properties props = new Properties(); - props.load(fr); - Map optionSettings = new HashMap<>(); - for (Map.Entry e : props.entrySet()) { - optionSettings.put((String) e.getKey(), (String) e.getValue()); - } - try { - OptionsParser.parseOptions(optionSettings, null, loader); - if (allOptionsSettings == null) { - allOptionsSettings = new HashMap<>(optionSettings); - } else { - allOptionsSettings.putAll(optionSettings); - } - } catch (Throwable e) { - throw new InternalError("Error parsing an option from " + graalOptions, e); - } - } catch (IOException e) { - throw new InternalError("Error reading " + graalOptions, e); - } - } - } - - Map optionSettings = new HashMap<>(); - for (Entry e : savedProps.entrySet()) { - String name = e.getKey(); - if (name.startsWith(GRAAL_OPTION_PROPERTY_PREFIX)) { - if (name.equals("graal.PrintFlags") || name.equals("graal.ShowFlags")) { - System.err.println("The " + name + " option has been removed and will be ignored. Use -XX:+JVMCIPrintProperties instead."); - } else if (name.equals(GRAAL_OPTIONS_FILE_PROPERTY_NAME) || name.equals(GRAAL_VERSION_PROPERTY_NAME) || name.equals(PROFILE_OPTIONVALUE_PROPERTY_NAME)) { - // Ignore well known properties that do not denote an option - } else { - String value = e.getValue(); - optionSettings.put(name.substring(GRAAL_OPTION_PROPERTY_PREFIX.length()), value); - } - } - } - - OptionsParser.parseOptions(optionSettings, null, loader); - - if (allOptionsSettings == null) { - allOptionsSettings = optionSettings; - } else { - allOptionsSettings.putAll(optionSettings); - } - - if (Options.GraalCompileOnly.getValue() != null) { - graalCompileOnlyFilter = MethodFilter.parse(Options.GraalCompileOnly.getValue()); - if (graalCompileOnlyFilter.length == 0) { - graalCompileOnlyFilter = null; - } - } - if (graalCompileOnlyFilter != null || !Options.UseTrivialPrefixes.getValue()) { - /* - * Exercise this code path early to encourage loading now. This doesn't solve - * problem of deadlock during class loading but seems to eliminate it in - * practice. - */ - adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization); - adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple); - } - } - } - } - @Override public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) { - HotSpotGraalCompiler compiler = createCompiler(runtime, CompilerConfigurationFactory.selectFactory(null)); + HotSpotGraalCompiler compiler = createCompiler(runtime, options, CompilerConfigurationFactory.selectFactory(null, options)); // Only the HotSpotGraalRuntime associated with the compiler created via // jdk.vm.ci.runtime.JVMCIRuntime.getCompiler() is registered for receiving // VM events. @@ -223,36 +124,24 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto * @param compilerConfigurationFactory factory for the {@link CompilerConfiguration} */ @SuppressWarnings("try") - public static HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime, CompilerConfigurationFactory compilerConfigurationFactory) { + public static HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory compilerConfigurationFactory) { HotSpotJVMCIRuntime jvmciRuntime = (HotSpotJVMCIRuntime) runtime; try (InitTimer t = timer("HotSpotGraalRuntime.")) { - HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(jvmciRuntime, compilerConfigurationFactory); - return new HotSpotGraalCompiler(jvmciRuntime, graalRuntime); + HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(jvmciRuntime, compilerConfigurationFactory, options); + return new HotSpotGraalCompiler(jvmciRuntime, graalRuntime, graalRuntime.getOptions()); } } - @Override - public String[] getTrivialPrefixes() { - if (Options.UseTrivialPrefixes.getValue()) { - if (Options.CompileGraalWithC1Only.getValue()) { - return new String[]{"jdk/vm/ci", "org/graalvm/compiler", "com/oracle/graal"}; - } - } - return null; - } - @Override public CompilationLevelAdjustment getCompilationLevelAdjustment() { if (graalCompileOnlyFilter != null) { return CompilationLevelAdjustment.ByFullSignature; } - if (!Options.UseTrivialPrefixes.getValue()) { - if (Options.CompileGraalWithC1Only.getValue()) { - // We only decide using the class declaring the method - // so no need to have the method name and signature - // symbols converted to a String. - return CompilationLevelAdjustment.ByHolder; - } + if (compileGraalWithC1Only) { + // We only decide using the class declaring the method + // so no need to have the method name and signature + // symbols converted to a String. + return CompilationLevelAdjustment.ByHolder; } return CompilationLevelAdjustment.None; } @@ -262,13 +151,31 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto return adjustCompilationLevelInternal(declaringClass, name, signature, level); } + static { + // Fail-fast detection for package renaming to guard use of package + // prefixes in adjustCompilationLevelInternal. + assert jdk.vm.ci.services.Services.class.getName().equals("jdk.vm.ci.services.Services"); + assert HotSpotGraalCompilerFactory.class.getName().equals("org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory"); + } + /* * This method is static so it can be exercised during initialization. */ private static CompilationLevel adjustCompilationLevelInternal(Class declaringClass, String name, String signature, CompilationLevel level) { + if (compileGraalWithC1Only) { + if (level.ordinal() > CompilationLevel.Simple.ordinal()) { + String declaringClassName = declaringClass.getName(); + if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm") || declaringClassName.startsWith("com.oracle.graal")) { + return CompilationLevel.Simple; + } + } + } + return checkGraalCompileOnlyFilter(declaringClass.getName(), name, signature, level); + } + + public static CompilationLevel checkGraalCompileOnlyFilter(String declaringClassName, String name, String signature, CompilationLevel level) { if (graalCompileOnlyFilter != null) { if (level == CompilationLevel.FullOptimization) { - String declaringClassName = declaringClass.getName(); HotSpotSignature sig = null; for (MethodFilter filter : graalCompileOnlyFilter) { if (filter.hasSignature() && sig == null) { @@ -281,12 +188,6 @@ public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFacto return CompilationLevel.Simple; } } - if (level.ordinal() > CompilationLevel.Simple.ordinal()) { - String declaringClassName = declaringClass.getName(); - if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm.compiler") || declaringClassName.startsWith("com.oracle.graal")) { - return CompilationLevel.Simple; - } - } return level; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java new file mode 100644 index 00000000000..c32e26808f1 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot; + +import java.lang.ref.Reference; +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; +import jdk.vm.ci.hotspot.HotSpotCompilationRequest; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.meta.MetaUtil; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.runtime.JVMCI; + +import org.graalvm.compiler.debug.DebugOptions; +import org.graalvm.compiler.options.OptionDescriptor; +import org.graalvm.compiler.options.OptionDescriptors; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.options.OptionsParser; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.EconomicSet; +import org.graalvm.util.Equivalence; +import org.graalvm.util.UnmodifiableEconomicMap; + +public final class HotSpotGraalMBean implements javax.management.DynamicMBean { + private static Object mBeanServerField; + private final HotSpotGraalCompiler compiler; + private final OptionValues options; + private final EconomicMap, Object> changes; + private final EconomicSet methodDumps; + private volatile EconomicSet> loaders; + private javax.management.ObjectName registered; + private OptionValues cachedOptions; + + private HotSpotGraalMBean(HotSpotGraalCompiler compiler, OptionValues options) { + this.compiler = compiler; + this.options = options; + this.changes = EconomicMap.create(); + this.methodDumps = EconomicSet.create(); + EconomicSet> systemLoaderSet = EconomicSet.create(RefEquivalence.INSTANCE); + systemLoaderSet.add(new WeakReference<>(ClassLoader.getSystemClassLoader())); + this.loaders = systemLoaderSet; + } + + private static boolean isMXServerOn() { + if (mBeanServerField == null) { + try { + final Field field = java.lang.management.ManagementFactory.class.getDeclaredField("platformMBeanServer"); + field.setAccessible(true); + mBeanServerField = field; + } catch (Exception ex) { + mBeanServerField = java.lang.management.ManagementFactory.class; + } + } + if (mBeanServerField instanceof Field) { + try { + return ((Field) mBeanServerField).get(null) != null; + } catch (Exception ex) { + return true; + } + } else { + return false; + } + } + + public static HotSpotGraalMBean create(HotSpotGraalCompiler compiler) { + OptionValues options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS; + HotSpotGraalMBean mbean = new HotSpotGraalMBean(compiler, options); + return mbean; + } + + public javax.management.ObjectName ensureRegistered(boolean check) { + for (int cnt = 0;; cnt++) { + if (registered != null) { + return registered; + } + if (check && !isMXServerOn()) { + return null; + } + try { + javax.management.MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer(); + javax.management.ObjectName name = new javax.management.ObjectName("org.graalvm.compiler.hotspot:type=Options" + (cnt == 0 ? "" : cnt)); + mbs.registerMBean(this, name); + registered = name; + break; + } catch (javax.management.MalformedObjectNameException | javax.management.MBeanRegistrationException | javax.management.NotCompliantMBeanException ex) { + throw new IllegalStateException(ex); + } catch (javax.management.InstanceAlreadyExistsException ex) { + continue; + } + } + return registered; + } + + public OptionValues optionsFor(OptionValues initialValues, ResolvedJavaMethod forMethod) { + ensureRegistered(true); + if (forMethod instanceof HotSpotResolvedJavaMethod) { + HotSpotResolvedObjectType type = ((HotSpotResolvedJavaMethod) forMethod).getDeclaringClass(); + if (type instanceof HotSpotResolvedJavaType) { + Class clazz = ((HotSpotResolvedJavaType) type).mirror(); + Reference addNewRef = new WeakReference<>(clazz.getClassLoader()); + if (!loaders.contains(addNewRef)) { + EconomicSet> newLoaders = EconomicSet.create(RefEquivalence.INSTANCE, loaders); + newLoaders.add(addNewRef); + this.loaders = newLoaders; + } + } + } + return currentMap(initialValues, forMethod); + } + + private OptionValues currentMap(OptionValues initialValues, ResolvedJavaMethod method) { + if (changes.isEmpty() && methodDumps.isEmpty()) { + return initialValues; + } + OptionValues current = cachedOptions; + if (current == null) { + current = new OptionValues(initialValues, changes); + cachedOptions = current; + } + if (method != null) { + for (Dump request : methodDumps) { + final String clazzName = method.getDeclaringClass().getName(); + if (method.getName().equals(request.method) && clazzName.equals(request.clazz)) { + current = new OptionValues(current, DebugOptions.Dump, request.filter, + DebugOptions.PrintGraphHost, request.host, + DebugOptions.PrintBinaryGraphPort, request.port); + break; + } + } + } + return current; + } + + @Override + public Object getAttribute(String attribute) { + UnmodifiableEconomicMap, Object> map = currentMap(options, null).getMap(); + for (OptionKey k : map.getKeys()) { + if (k.getName().equals(attribute)) { + return map.get(k); + } + } + return null; + } + + @Override + public void setAttribute(javax.management.Attribute attribute) throws javax.management.AttributeNotFoundException { + javax.management.Attribute newAttr = setImpl(attribute); + if (newAttr == null) { + throw new javax.management.AttributeNotFoundException(); + } + } + + private javax.management.Attribute setImpl(javax.management.Attribute attribute) { + cachedOptions = null; + for (OptionDescriptor option : allOptionDescriptors()) { + if (option.getName().equals(attribute.getName())) { + changes.put(option.getOptionKey(), attribute.getValue()); + return attribute; + } + } + return null; + } + + @Override + public javax.management.AttributeList getAttributes(String[] names) { + javax.management.AttributeList list = new javax.management.AttributeList(); + for (String name : names) { + Object value = getAttribute(name); + if (value != null) { + list.add(new javax.management.Attribute(name, value)); + } + } + return list; + } + + @Override + public javax.management.AttributeList setAttributes(javax.management.AttributeList attributes) { + javax.management.AttributeList setOk = new javax.management.AttributeList(); + for (javax.management.Attribute attr : attributes.asList()) { + javax.management.Attribute newAttr = setImpl(attr); + if (newAttr != null) { + setOk.add(newAttr); + } + } + return setOk; + } + + @Override + public Object invoke(String actionName, Object[] params, String[] signature) throws javax.management.MBeanException, javax.management.ReflectionException { + if ("dumpMethod".equals(actionName)) { + try { + String className = param(params, 0, "className", String.class, null); + String methodName = param(params, 1, "methodName", String.class, null); + String filter = param(params, 2, "filter", String.class, ":3"); + String host = param(params, 3, "host", String.class, "localhost"); + Number port = param(params, 4, "port", Number.class, 4445); + dumpMethod(className, methodName, filter, host, port.intValue()); + } catch (Exception ex) { + throw new javax.management.ReflectionException(ex); + } + } + return null; + } + + private static T param(Object[] arr, int index, String name, Class type, T defaultValue) { + Object value = arr.length > index ? arr[index] : null; + if (value == null || (value instanceof String && ((String) value).isEmpty())) { + if (defaultValue == null) { + throw new IllegalArgumentException(name + " must be specified"); + } + value = defaultValue; + } + if (type.isInstance(value)) { + return type.cast(value); + } + throw new IllegalArgumentException("Expecting " + type.getName() + " for " + name + " but was " + value); + } + + public void dumpMethod(String className, String methodName, String filter, String host, int port) throws javax.management.MBeanException { + String jvmName = MetaUtil.toInternalName(className); + methodDumps.add(new Dump(host, port, jvmName, methodName, filter)); + + ClassNotFoundException last = null; + EconomicSet> found = EconomicSet.create(); + Iterator> it = loaders.iterator(); + while (it.hasNext()) { + Reference ref = it.next(); + ClassLoader loader = ref.get(); + if (loader == null) { + it.remove(); + continue; + } + try { + Class clazz = Class.forName(className, false, loader); + if (found.add(clazz)) { + ResolvedJavaType type = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaType(clazz); + if (compiler != null) { + for (ResolvedJavaMethod method : type.getDeclaredMethods()) { + if (methodName.equals(method.getName()) && method instanceof HotSpotResolvedJavaMethod) { + HotSpotResolvedJavaMethod hotSpotMethod = (HotSpotResolvedJavaMethod) method; + compiler.compileMethod(new HotSpotCompilationRequest(hotSpotMethod, -1, 0L), false); + } + } + } + } + } catch (ClassNotFoundException ex) { + last = ex; + } + } + if (found.isEmpty()) { + throw new javax.management.MBeanException(last, "Cannot find class " + className + " to schedule recompilation"); + } + } + + @Override + public javax.management.MBeanInfo getMBeanInfo() { + List attrs = new ArrayList<>(); + if (registered != null) { + for (OptionDescriptor descr : allOptionDescriptors()) { + attrs.add(new javax.management.MBeanAttributeInfo(descr.getName(), descr.getType().getName(), descr.getHelp(), true, true, false)); + } + } + javax.management.MBeanOperationInfo[] ops = { + new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{ + new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"), + new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"), + }, "void", javax.management.MBeanOperationInfo.ACTION), + new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{ + new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"), + new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"), + new javax.management.MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"), + }, "void", javax.management.MBeanOperationInfo.ACTION), + new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{ + new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"), + new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"), + new javax.management.MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"), + new javax.management.MBeanParameterInfo("host", "java.lang.String", "The host where the IGV tool is running at"), + new javax.management.MBeanParameterInfo("port", "int", "The port where the IGV tool is listening at"), + }, "void", javax.management.MBeanOperationInfo.ACTION) + }; + + return new javax.management.MBeanInfo( + HotSpotGraalMBean.class.getName(), + "Graal", + attrs.toArray(new javax.management.MBeanAttributeInfo[attrs.size()]), + null, ops, null); + } + + private static Iterable allOptionDescriptors() { + List arr = new ArrayList<>(); + for (OptionDescriptors set : OptionsParser.getOptionsLoader()) { + for (OptionDescriptor descr : set) { + arr.add(descr); + } + } + return arr; + } + + private static final class Dump { + final String host; + final int port; + final String clazz; + final String method; + final String filter; + + Dump(String host, int port, String clazz, String method, String filter) { + this.host = host; + this.port = port; + this.clazz = clazz; + this.method = method; + this.filter = filter; + } + } + + private static final class RefEquivalence extends Equivalence { + static final Equivalence INSTANCE = new RefEquivalence(); + + private RefEquivalence() { + } + + @Override + public boolean equals(Object a, Object b) { + Reference refA = (Reference) a; + Reference refB = (Reference) b; + return Objects.equals(refA.get(), refB.get()); + } + + @Override + public int hashCode(Object o) { + Reference ref = (Reference) o; + Object obj = ref.get(); + return obj == null ? 0 : obj.hashCode(); + } + + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java new file mode 100644 index 00000000000..2fde550dd64 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot; + +import static jdk.vm.ci.common.InitTimer.timer; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Map; +import java.util.Properties; + +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionDescriptors; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.options.OptionValuesAccess; +import org.graalvm.compiler.options.OptionsParser; +import org.graalvm.compiler.serviceprovider.ServiceProvider; +import org.graalvm.util.EconomicMap; + +import jdk.vm.ci.common.InitTimer; + +/** + * The {@link #HOTSPOT_OPTIONS} value contains the options values initialized in a HotSpot VM. The + * values are set via system properties with the {@value #GRAAL_OPTION_PROPERTY_PREFIX} prefix. + */ +@ServiceProvider(OptionValuesAccess.class) +public class HotSpotGraalOptionValues implements OptionValuesAccess { + + /** + * The name of the system property specifying a file containing extra Graal option settings. + */ + private static final String GRAAL_OPTIONS_FILE_PROPERTY_NAME = "graal.options.file"; + + /** + * The name of the system property specifying the Graal version. + */ + private static final String GRAAL_VERSION_PROPERTY_NAME = "graal.version"; + + /** + * The prefix for system properties that correspond to {@link Option} annotated fields. A field + * named {@code MyOption} will have its value set from a system property with the name + * {@code GRAAL_OPTION_PROPERTY_PREFIX + "MyOption"}. + */ + public static final String GRAAL_OPTION_PROPERTY_PREFIX = "graal."; + + /** + * Gets the system property assignment that would set the current value for a given option. + */ + public static String asSystemPropertySetting(OptionValues options, OptionKey value) { + return GRAAL_OPTION_PROPERTY_PREFIX + value.getName() + "=" + value.getValue(options); + } + + public static final OptionValues HOTSPOT_OPTIONS = initializeOptions(); + + /** + * Global options. The values for these options are initialized by parsing the file denoted by + * the {@code VM.getSavedProperty(String) saved} system property named + * {@value #GRAAL_OPTIONS_FILE_PROPERTY_NAME} if the file exists followed by parsing the options + * encoded in saved system properties whose names start with + * {@value #GRAAL_OPTION_PROPERTY_PREFIX}. Key/value pairs are parsed from the aforementioned + * file with {@link Properties#load(java.io.Reader)}. + */ + @SuppressWarnings("try") + private static OptionValues initializeOptions() { + EconomicMap, Object> values = OptionValues.newOptionMap(); + try (InitTimer t = timer("InitializeOptions")) { + + Iterable loader = OptionsParser.getOptionsLoader(); + Map savedProps = jdk.vm.ci.services.Services.getSavedProperties(); + String optionsFile = savedProps.get(GRAAL_OPTIONS_FILE_PROPERTY_NAME); + + if (optionsFile != null) { + File graalOptions = new File(optionsFile); + if (graalOptions.exists()) { + try (FileReader fr = new FileReader(graalOptions)) { + Properties props = new Properties(); + props.load(fr); + EconomicMap optionSettings = EconomicMap.create(); + for (Map.Entry e : props.entrySet()) { + optionSettings.put((String) e.getKey(), (String) e.getValue()); + } + try { + OptionsParser.parseOptions(optionSettings, values, loader); + } catch (Throwable e) { + throw new InternalError("Error parsing an option from " + graalOptions, e); + } + } catch (IOException e) { + throw new InternalError("Error reading " + graalOptions, e); + } + } + } + + EconomicMap optionSettings = EconomicMap.create(); + for (Map.Entry e : savedProps.entrySet()) { + String name = e.getKey(); + if (name.startsWith(GRAAL_OPTION_PROPERTY_PREFIX)) { + if (name.equals("graal.PrintFlags") || name.equals("graal.ShowFlags")) { + System.err.println("The " + name + " option has been removed and will be ignored. Use -XX:+JVMCIPrintProperties instead."); + } else if (name.equals(GRAAL_OPTIONS_FILE_PROPERTY_NAME) || name.equals(GRAAL_VERSION_PROPERTY_NAME)) { + // Ignore well known properties that do not denote an option + } else { + String value = e.getValue(); + optionSettings.put(name.substring(GRAAL_OPTION_PROPERTY_PREFIX.length()), value); + } + } + } + + OptionsParser.parseOptions(optionSettings, values, loader); + return new OptionValues(values); + } + } + + @Override + public OptionValues getOptions() { + return HOTSPOT_OPTIONS; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java index 401169124f4..3e433b13378 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java @@ -22,41 +22,43 @@ */ package org.graalvm.compiler.hotspot; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.debug.GraalDebugConfig.areScopedGlobalMetricsEnabled; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.DebugValueSummary; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Dump; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Log; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.MethodFilter; -import static org.graalvm.compiler.debug.GraalDebugConfig.Options.Verify; import static jdk.vm.ci.common.InitTimer.timer; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; +import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; +import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM; -import java.util.Collections; -import java.util.HashMap; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; import java.util.Map; -import org.graalvm.compiler.api.collections.CollectionsProvider; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.api.runtime.GraalRuntime; +import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction; +import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugEnvironment; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Description; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DiagnosticsOutputDirectory; +import org.graalvm.compiler.debug.GlobalMetrics; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; -import org.graalvm.compiler.debug.internal.DebugValuesPrinter; -import org.graalvm.compiler.debug.internal.method.MethodMetricsPrinter; -import org.graalvm.compiler.graph.DefaultNodeCollectionsProvider; -import org.graalvm.compiler.graph.NodeCollectionsProvider; +import org.graalvm.compiler.hotspot.CompilationStatistics.Options; import org.graalvm.compiler.hotspot.CompilerConfigurationFactory.BackendMap; import org.graalvm.compiler.hotspot.debug.BenchmarkCounters; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.spi.StampProvider; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.runtime.RuntimeProvider; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.stack.StackIntrospection; @@ -64,6 +66,7 @@ import jdk.vm.ci.common.InitTimer; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.runtime.JVMCIBackend; //JaCoCo Exclude @@ -86,29 +89,42 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { } private final HotSpotBackend hostBackend; - private DebugValuesPrinter debugValuesPrinter; + private final GlobalMetrics metricValues = new GlobalMetrics(); + private final List snippetCounterGroups; - private final Map, HotSpotBackend> backends = new HashMap<>(); + private final EconomicMap, HotSpotBackend> backends = EconomicMap.create(Equivalence.IDENTITY); private final GraalHotSpotVMConfig config; + private final OptionValues options; + private final DiagnosticsOutputDirectory outputDirectory; + private final Map compilationProblemsPerAction; + private final HotSpotGraalMBean mBean; + /** * @param compilerConfigurationFactory factory for the compiler configuration - * {@link CompilerConfigurationFactory#selectFactory(String)} + * {@link CompilerConfigurationFactory#selectFactory(String, OptionValues)} */ @SuppressWarnings("try") - HotSpotGraalRuntime(HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory) { - + HotSpotGraalRuntime(HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory, OptionValues initialOptions) { HotSpotVMConfigStore store = jvmciRuntime.getConfigStore(); - config = GeneratePIC.getValue() ? new AOTGraalHotSpotVMConfig(store) : new GraalHotSpotVMConfig(store); - CompileTheWorldOptions.overrideWithNativeOptions(config); + config = GeneratePIC.getValue(initialOptions) ? new AOTGraalHotSpotVMConfig(store) : new GraalHotSpotVMConfig(store); // Only set HotSpotPrintInlining if it still has its default value (false). - if (GraalOptions.HotSpotPrintInlining.getValue() == false) { - GraalOptions.HotSpotPrintInlining.setValue(config.printInlining); + if (GraalOptions.HotSpotPrintInlining.getValue(initialOptions) == false && config.printInlining) { + options = new OptionValues(initialOptions, HotSpotPrintInlining, true); + } else { + options = initialOptions; } + outputDirectory = new DiagnosticsOutputDirectory(options); + compilationProblemsPerAction = new EnumMap<>(ExceptionAction.class); + snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null; CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration(); + + HotSpotGraalCompiler compiler = new HotSpotGraalCompiler(jvmciRuntime, this, initialOptions); + this.mBean = createHotSpotGraalMBean(compiler); + BackendMap backendMap = compilerConfigurationFactory.createBackendMap(); JVMCIBackend hostJvmciBackend = jvmciRuntime.getHostJVMCIBackend(); @@ -136,69 +152,19 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { } } - if (Log.getValue() == null && !areScopedGlobalMetricsEnabled() && Dump.getValue() == null && Verify.getValue() == null) { - if (MethodFilter.getValue() != null && !Debug.isEnabled()) { - TTY.println("WARNING: Ignoring MethodFilter option since Log, Meter, Time, TrackMemUse, Dump and Verify options are all null"); - } - } - - if (Debug.isEnabled()) { - DebugEnvironment.initialize(TTY.out, hostBackend.getProviders().getSnippetReflection()); - - String summary = DebugValueSummary.getValue(); - if (summary != null) { - switch (summary) { - case "Name": - case "Partial": - case "Complete": - case "Thread": - break; - default: - throw new GraalError("Unsupported value for DebugSummaryValue: %s", summary); - } - } - } - - if (Debug.areUnconditionalCountersEnabled() || Debug.areUnconditionalTimersEnabled() || Debug.areUnconditionalMethodMetricsEnabled() || - (Debug.isEnabled() && areScopedGlobalMetricsEnabled()) || (Debug.isEnabled() && Debug.isMethodFilteringEnabled())) { - // This must be created here to avoid loading the DebugValuesPrinter class - // during shutdown() which in turn can cause a deadlock - int mmPrinterType = 0; - mmPrinterType |= MethodMetricsPrinter.Options.MethodMeterPrintAscii.getValue() ? 1 : 0; - mmPrinterType |= MethodMetricsPrinter.Options.MethodMeterFile.getValue() != null ? 2 : 0; - switch (mmPrinterType) { - case 0: - debugValuesPrinter = new DebugValuesPrinter(); - break; - case 1: - debugValuesPrinter = new DebugValuesPrinter(new MethodMetricsPrinter.MethodMetricsASCIIPrinter(TTY.out)); - break; - case 2: - debugValuesPrinter = new DebugValuesPrinter(new MethodMetricsPrinter.MethodMetricsCSVFilePrinter()); - break; - case 3: - debugValuesPrinter = new DebugValuesPrinter( - new MethodMetricsPrinter.MethodMetricsCompositePrinter(new MethodMetricsPrinter.MethodMetricsCSVFilePrinter(), - new MethodMetricsPrinter.MethodMetricsASCIIPrinter(TTY.out))); - break; - default: - break; - } - } - // Complete initialization of backends try (InitTimer st = timer(hostBackend.getTarget().arch.getName(), ".completeInitialization")) { - hostBackend.completeInitialization(jvmciRuntime); + hostBackend.completeInitialization(jvmciRuntime, options); } - for (HotSpotBackend backend : backends.values()) { + for (HotSpotBackend backend : backends.getValues()) { if (backend != hostBackend) { try (InitTimer st = timer(backend.getTarget().arch.getName(), ".completeInitialization")) { - backend.completeInitialization(jvmciRuntime); + backend.completeInitialization(jvmciRuntime, options); } } } - BenchmarkCounters.initialize(jvmciRuntime); + BenchmarkCounters.initialize(jvmciRuntime, options); assert checkArrayIndexScaleInvariants(); @@ -206,6 +172,14 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { bootstrapJVMCI = config.getFlag("BootstrapJVMCI", Boolean.class); } + private static HotSpotGraalMBean createHotSpotGraalMBean(HotSpotGraalCompiler compiler) { + try { + return HotSpotGraalMBean.create(compiler); + } catch (LinkageError ex) { + return null; + } + } + private HotSpotBackend registerBackend(HotSpotBackend backend) { Class arch = backend.getTarget().arch.getClass(); HotSpotBackend oldValue = backends.put(arch, backend); @@ -223,20 +197,44 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { return config; } + @Override + public DebugContext openDebugContext(OptionValues compilationOptions, CompilationIdentifier compilationId, Object compilable, Iterable factories) { + Description description = new Description(compilable, compilationId.toString(CompilationIdentifier.Verbosity.ID)); + return DebugContext.create(compilationOptions, description, metricValues, DEFAULT_LOG_STREAM, factories); + } + + @Override + public OptionValues getOptions() { + return mBean == null ? options : mBean.optionsFor(options, null); + } + + @Override + public OptionValues getOptions(ResolvedJavaMethod forMethod) { + return mBean == null ? options : mBean.optionsFor(options, forMethod); + } + + @Override + public Group createSnippetCounterGroup(String name) { + if (snippetCounterGroups != null) { + Group group = new Group(name); + snippetCounterGroups.add(group); + return group; + } + return null; + } + @Override public String getName() { return getClass().getSimpleName(); } - private final NodeCollectionsProvider nodeCollectionsProvider = new DefaultNodeCollectionsProvider(); - @SuppressWarnings("unchecked") @Override public T getCapability(Class clazz) { if (clazz == RuntimeProvider.class) { return (T) this; - } else if (clazz == CollectionsProvider.class || clazz == NodeCollectionsProvider.class) { - return (T) nodeCollectionsProvider; + } else if (clazz == OptionValues.class) { + return (T) options; } else if (clazz == StackIntrospection.class) { return (T) this; } else if (clazz == SnippetReflectionProvider.class) { @@ -258,35 +256,38 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { return backends.get(arch); } - public Map, HotSpotBackend> getBackends() { - return Collections.unmodifiableMap(backends); - } - private long runtimeStartTime; + private boolean shutdown; /** * Take action related to entering a new execution phase. * * @param phase the execution phase being entered */ - static void phaseTransition(String phase) { - CompilationStatistics.clear(phase); + void phaseTransition(String phase) { + if (Options.UseCompilationStatistics.getValue(options)) { + CompilationStatistics.clear(phase); + } } void shutdown() { - if (debugValuesPrinter != null) { - debugValuesPrinter.printDebugValues(); - } + shutdown = true; + metricValues.print(options); + phaseTransition("final"); - SnippetCounter.printGroups(TTY.out().out()); - BenchmarkCounters.shutdown(runtime(), runtimeStartTime); + if (snippetCounterGroups != null) { + for (Group group : snippetCounterGroups) { + TTY.out().out().println(group); + } + } + BenchmarkCounters.shutdown(runtime(), options, runtimeStartTime); + + outputDirectory.close(); } - void clearMeters() { - if (debugValuesPrinter != null) { - debugValuesPrinter.clearDebugValues(); - } + void clearMetrics() { + metricValues.clear(); } private final boolean bootstrapJVMCI; @@ -300,4 +301,19 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider { public boolean isBootstrapping() { return bootstrapJVMCI && !bootstrapFinished; } + + @Override + public boolean isShutdown() { + return shutdown; + } + + @Override + public DiagnosticsOutputDirectory getOutputDirectory() { + return outputDirectory; + } + + @Override + public Map getCompilationProblemsPerAction() { + return compilationProblemsPerAction; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java index f662ab8757c..6cacaf9a2cf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java @@ -22,18 +22,28 @@ */ package org.graalvm.compiler.hotspot; +import java.util.Map; + import org.graalvm.compiler.api.runtime.GraalRuntime; +import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction; +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.debug.DebugHandlersFactory; +import org.graalvm.compiler.debug.DiagnosticsOutputDirectory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.runtime.RuntimeProvider; import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.ResolvedJavaMethod; //JaCoCo Exclude /** * Configuration information for the HotSpot Graal runtime. */ -public interface HotSpotGraalRuntimeProvider extends GraalRuntime, RuntimeProvider { +public interface HotSpotGraalRuntimeProvider extends GraalRuntime, RuntimeProvider, Group.Factory { default TargetDescription getTarget() { return getHostBackend().getTarget(); @@ -51,8 +61,46 @@ public interface HotSpotGraalRuntimeProvider extends GraalRuntime, RuntimeProvid GraalHotSpotVMConfig getVMConfig(); + /** + * Opens a debug context for compiling {@code compilable}. The {@link DebugContext#close()} + * method should be called on the returned object once the compilation is finished. + * + * @param compilationOptions the options used to configure the compilation debug context + * @param compilationId a system wide unique compilation id + * @param compilable the input to the compilation + */ + DebugContext openDebugContext(OptionValues compilationOptions, CompilationIdentifier compilationId, Object compilable, Iterable factories); + + /** + * Gets the option values associated with this runtime. + */ + OptionValues getOptions(); + + /** + * Gets the option values associated with this runtime that are applicable for a given method. + * + * @param forMethod the method we are seeking for options for + * @return the options applicable for compiling {@code method} + */ + OptionValues getOptions(ResolvedJavaMethod forMethod); + /** * Determines if the VM is currently bootstrapping the JVMCI compiler. */ boolean isBootstrapping(); + + /** + * This runtime has been requested to shutdown. + */ + boolean isShutdown(); + + /** + * Gets a directory into which diagnostics such crash reports and dumps should be written. + */ + DiagnosticsOutputDirectory getOutputDirectory(); + + /** + * Gets the map used to count compilation problems at each {@link ExceptionAction} level. + */ + Map getCompilationProblemsPerAction(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java index 64d1073e80a..4d9e1784f62 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java @@ -22,9 +22,13 @@ */ package org.graalvm.compiler.hotspot; +import java.util.ArrayList; +import java.util.List; + import org.graalvm.compiler.code.CompilationResult; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.GraalDebugConfig; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugOptions; +import org.graalvm.compiler.serviceprovider.GraalServices; import jdk.vm.ci.code.CompiledCode; import jdk.vm.ci.code.InstalledCode; @@ -34,9 +38,14 @@ import jdk.vm.ci.hotspot.HotSpotVMEventListener; public class HotSpotGraalVMEventListener implements HotSpotVMEventListener { private final HotSpotGraalRuntime runtime; + private List listeners; HotSpotGraalVMEventListener(HotSpotGraalRuntime runtime) { this.runtime = runtime; + listeners = new ArrayList<>(); + for (HotSpotCodeCacheListener listener : GraalServices.load(HotSpotCodeCacheListener.class)) { + listeners.add(listener); + } } @Override @@ -46,21 +55,25 @@ public class HotSpotGraalVMEventListener implements HotSpotVMEventListener { @Override public void notifyInstall(HotSpotCodeCacheProvider codeCache, InstalledCode installedCode, CompiledCode compiledCode) { - if (Debug.isDumpEnabled(Debug.BASIC_LOG_LEVEL)) { - CompilationResult compResult = Debug.contextLookup(CompilationResult.class); + DebugContext debug = DebugContext.forCurrentThread(); + if (debug.isDumpEnabled(DebugContext.BASIC_LEVEL)) { + CompilationResult compResult = debug.contextLookup(CompilationResult.class); assert compResult != null : "can't dump installed code properly without CompilationResult"; - Debug.dump(Debug.BASIC_LOG_LEVEL, installedCode, "After code installation"); + debug.dump(DebugContext.BASIC_LEVEL, installedCode, "After code installation"); } - if (Debug.isLogEnabled()) { - Debug.log("%s", codeCache.disassemble(installedCode)); + if (debug.isLogEnabled()) { + debug.log("%s", codeCache.disassemble(installedCode)); + } + for (HotSpotCodeCacheListener listener : listeners) { + listener.notifyInstall(codeCache, installedCode, compiledCode); } } @Override public void notifyBootstrapFinished() { runtime.notifyBootstrapFinished(); - if (GraalDebugConfig.Options.ClearMetricsAfterBootstrap.getValue()) { - runtime.clearMeters(); + if (DebugOptions.ClearMetricsAfterBootstrap.getValue(runtime.getOptions())) { + runtime.clearMetrics(); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java index 8df8a9c82ae..968e81506ad 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotHostBackend.java @@ -22,19 +22,24 @@ */ package org.graalvm.compiler.hotspot; +import static jdk.vm.ci.code.CodeUtil.K; import static jdk.vm.ci.code.CodeUtil.getCallingConvention; import static jdk.vm.ci.common.InitTimer.timer; +import java.util.Collections; + +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotLoweringProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.stubs.DeoptimizationStub; import org.graalvm.compiler.hotspot.stubs.Stub; -import org.graalvm.compiler.hotspot.stubs.UncommonTrapStub; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.ReferenceMapBuilder; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.common.InitTimer; @@ -49,16 +54,12 @@ import jdk.vm.ci.runtime.JVMCICompiler; public abstract class HotSpotHostBackend extends HotSpotBackend { /** - * Descriptor for {@code SharedRuntime::deopt_blob()->unpack()} or - * {@link DeoptimizationStub#deoptimizationHandler} depending on - * {@link HotSpotBackend.Options#PreferGraalStubs}. + * Descriptor for {@code SharedRuntime::deopt_blob()->unpack()}. */ public static final ForeignCallDescriptor DEOPTIMIZATION_HANDLER = new ForeignCallDescriptor("deoptHandler", void.class); /** - * Descriptor for {@code SharedRuntime::deopt_blob()->uncommon_trap()} or - * {@link UncommonTrapStub#uncommonTrapHandler} depending on - * {@link HotSpotBackend.Options#PreferGraalStubs}. + * Descriptor for {@code SharedRuntime::deopt_blob()->uncommon_trap()}. */ public static final ForeignCallDescriptor UNCOMMON_TRAP_HANDLER = new ForeignCallDescriptor("uncommonTrapHandler", void.class); @@ -71,16 +72,17 @@ public abstract class HotSpotHostBackend extends HotSpotBackend { @Override @SuppressWarnings("try") - public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime) { + public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options) { final HotSpotProviders providers = getProviders(); HotSpotHostForeignCallsProvider foreignCalls = (HotSpotHostForeignCallsProvider) providers.getForeignCalls(); final HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); try (InitTimer st = timer("foreignCalls.initialize")) { - foreignCalls.initialize(providers); + foreignCalls.initialize(providers, options); } try (InitTimer st = timer("lowerer.initialize")) { - lowerer.initialize(providers, config); + Iterable factories = Collections.singletonList(new GraalDebugHandlersFactory(providers.getSnippetReflection())); + lowerer.initialize(options, factories, providers, config); } } @@ -114,7 +116,7 @@ public abstract class HotSpotHostBackend extends HotSpotBackend { // is greater than a page. int pageSize = config.vmPageSize; - int bangEnd = config.stackShadowPages * pageSize; + int bangEnd = NumUtil.roundUp(config.stackShadowPages * 4 * K, pageSize); // This is how far the previous frame's stack banging extended. int bangEndSafe = bangEnd; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java index 8b91390bfb9..a0d05bd48df 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotInstructionProfiling.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.hotspot; -import java.util.List; +import java.util.ArrayList; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Assembler.InstructionCounter; @@ -80,7 +80,7 @@ public class HotSpotInstructionProfiling extends PostAllocationOptimizationPhase } public void doBlock(AbstractBlockBase block) { - List instructions = lir.getLIRforBlock(block); + ArrayList instructions = lir.getLIRforBlock(block); assert instructions.size() >= 2 : "Malformed block: " + block + ", " + instructions; assert instructions.get(instructions.size() - 1) instanceof BlockEndOp : "Not a BlockEndOp: " + instructions.get(instructions.size() - 1); assert !(instructions.get(instructions.size() - 2) instanceof BlockEndOp) : "Is a BlockEndOp: " + instructions.get(instructions.size() - 2); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java index 11383b77a7c..f3543dd8fed 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java @@ -22,9 +22,6 @@ */ package org.graalvm.compiler.hotspot; -import java.util.Map; - -import org.graalvm.compiler.core.common.CollectionsFactory; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.lir.LIR; @@ -32,6 +29,8 @@ import org.graalvm.compiler.lir.LIRFrameState; import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.framemap.FrameMapBuilder; import org.graalvm.compiler.lir.gen.LIRGenerationResult; +import org.graalvm.util.Equivalence; +import org.graalvm.util.EconomicMap; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.StackSlot; @@ -52,14 +51,14 @@ public class HotSpotLIRGenerationResult extends LIRGenerationResult { * Map from debug infos that need to be updated with callee save information to the operations * that provide the information. */ - private Map calleeSaveInfo = CollectionsFactory.newMap(); + private EconomicMap calleeSaveInfo = EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE); public HotSpotLIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, CallingConvention callingConvention, Object stub) { super(compilationId, lir, frameMapBuilder, callingConvention); this.stub = stub; } - public Map getCalleeSaveInfo() { + public EconomicMap getCalleeSaveInfo() { return calleeSaveInfo; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java index f2f45e24fec..199d51f58c7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerator.java @@ -26,22 +26,13 @@ import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.DeoptimizationFetchUnrollInfoCallNode; -import org.graalvm.compiler.hotspot.nodes.EnterUnpackFramesStackFrameNode; import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; -import org.graalvm.compiler.hotspot.nodes.LeaveCurrentStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveDeoptimizedStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveUnpackFramesStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.PushInterpreterFrameNode; -import org.graalvm.compiler.hotspot.nodes.SaveAllRegistersNode; -import org.graalvm.compiler.hotspot.nodes.UncommonTrapCallNode; import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; import org.graalvm.compiler.hotspot.nodes.profiling.RandomSeedNode; import org.graalvm.compiler.hotspot.replacements.EncodedSymbolConstant; import org.graalvm.compiler.lir.LIRFrameState; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.VirtualStackSlot; import org.graalvm.compiler.lir.gen.LIRGenerator; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; @@ -70,65 +61,6 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool { void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason); - /** - * Emits code for a {@link SaveAllRegistersNode}. - * - * @return a {@link SaveRegistersOp} operation - */ - SaveRegistersOp emitSaveAllRegisters(); - - /** - * Emits code for a {@link LeaveCurrentStackFrameNode}. - * - * @param saveRegisterOp saved registers - */ - default void emitLeaveCurrentStackFrame(SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link LeaveDeoptimizedStackFrameNode}. - * - * @param frameSize - * @param initialInfo - */ - default void emitLeaveDeoptimizedStackFrame(Value frameSize, Value initialInfo) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link EnterUnpackFramesStackFrameNode}. - * - * @param framePc - * @param senderSp - * @param senderFp - * @param saveRegisterOp - */ - default void emitEnterUnpackFramesStackFrame(Value framePc, Value senderSp, Value senderFp, SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link LeaveUnpackFramesStackFrameNode}. - * - * @param saveRegisterOp - */ - default void emitLeaveUnpackFramesStackFrame(SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link PushInterpreterFrameNode}. - * - * @param frameSize - * @param framePc - * @param senderSp - * @param initialInfo - */ - default void emitPushInterpreterFrame(Value frameSize, Value framePc, Value senderSp, Value initialInfo) { - throw GraalError.unimplemented(); - } - /** * Emits code for a {@link LoadConstantIndirectlyNode}. * @@ -227,29 +159,6 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool { throw GraalError.unimplemented(); } - /** - * Emits code for a {@link UncommonTrapCallNode}. - * - * @param trapRequest - * @param mode - * @param saveRegisterOp - * @return a {@code Deoptimization::UnrollBlock} pointer - */ - default Value emitUncommonTrapCall(Value trapRequest, Value mode, SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - - /** - * Emits code for a {@link DeoptimizationFetchUnrollInfoCallNode}. - * - * @param mode - * @param saveRegisterOp - * @return a {@code Deoptimization::UnrollBlock} pointer - */ - default Value emitDeoptimizationFetchUnrollInfoCall(Value mode, SaveRegistersOp saveRegisterOp) { - throw GraalError.unimplemented(); - } - /** * Gets a stack slot for a lock at a given lock nesting depth. */ @@ -258,8 +167,4 @@ public interface HotSpotLIRGenerator extends LIRGeneratorTool { @Override HotSpotProviders getProviders(); - Value emitCompress(Value pointer, CompressEncoding encoding, boolean nonNull); - - Value emitUncompress(Value pointer, CompressEncoding encoding, boolean nonNull); - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotNodeLIRBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotNodeLIRBuilder.java index 7dc534a29a9..9b0dd3cfcbf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotNodeLIRBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotNodeLIRBuilder.java @@ -23,9 +23,8 @@ package org.graalvm.compiler.hotspot; import org.graalvm.compiler.core.match.MatchableNode; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.lir.gen.LIRGenerator; +import org.graalvm.compiler.nodes.CompressionNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; @@ -43,7 +42,4 @@ public interface HotSpotNodeLIRBuilder { } void emitJumpToExceptionHandlerInCaller(ValueNode handlerInCallerPc, ValueNode exception, ValueNode exceptionPc); - - void visitDirectCompareAndSwap(DirectCompareAndSwapNode x); - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReferenceMapBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReferenceMapBuilder.java index a8b7982ebf4..97fc0fd01ed 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReferenceMapBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReferenceMapBuilder.java @@ -29,7 +29,7 @@ import static jdk.vm.ci.code.ValueUtil.isRegister; import java.util.ArrayList; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRFrameState; @@ -104,7 +104,7 @@ public final class HotSpotReferenceMapBuilder extends ReferenceMapBuilder { LIRKind kind = (LIRKind) obj.getValueKind(); int bytes = bytesPerElement(kind); if (kind.isUnknownReference()) { - throw GraalError.shouldNotReachHere("unknown reference alive across safepoint"); + throw GraalError.shouldNotReachHere(String.format("unknown reference alive across safepoint: %s", obj)); } else { Location base = null; if (kind.isDerivedReference()) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java index dc52af69b7a..ca78ffa9fa1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java @@ -25,7 +25,9 @@ package org.graalvm.compiler.hotspot; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeProvider; import org.graalvm.compiler.hotspot.word.HotSpotOperation; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; import org.graalvm.compiler.replacements.ReplacementsImpl; import jdk.vm.ci.code.TargetDescription; @@ -37,8 +39,8 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; */ public class HotSpotReplacementsImpl extends ReplacementsImpl { - public HotSpotReplacementsImpl(Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { - super(providers, snippetReflection, bytecodeProvider, target); + public HotSpotReplacementsImpl(OptionValues options, Providers providers, SnippetReflectionProvider snippetReflection, BytecodeProvider bytecodeProvider, TargetDescription target) { + super(options, new GraalDebugHandlersFactory(snippetReflection), providers, snippetReflection, bytecodeProvider, target); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java index 8bd1710f9e7..0a8fe40f6f9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.hotspot; +import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.HOTSPOT_OPTIONS; + import java.io.PrintStream; import org.graalvm.compiler.debug.TTYStreamProvider; @@ -36,13 +38,13 @@ public class HotSpotTTYStreamProvider implements TTYStreamProvider { // @formatter:off @Option(help = "File to which logging is sent. A %p in the name will be replaced with a string identifying " + - "the process, usually the process id and %t will be replaced by System.currentTimeMillis().", type = OptionType.Expert) - public static final PrintStreamOption LogFile = new PrintStreamOption(); + "the process, usually the process id and %t will be replaced by System.currentTimeMillis().", type = OptionType.Expert) + public static final PrintStreamOptionKey LogFile = new PrintStreamOptionKey(); // @formatter:on } @Override public PrintStream getStream() { - return Options.LogFile.getStream(); + return Options.LogFile.getStream(HOTSPOT_OPTIONS); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java index ba759b73abb..8ec974534be 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java @@ -38,7 +38,7 @@ import java.util.Objects; class JVMCIVersionCheck { private static final int JVMCI8_MIN_MAJOR_VERSION = 0; - private static final int JVMCI8_MIN_MINOR_VERSION = 26; + private static final int JVMCI8_MIN_MINOR_VERSION = 29; // MAX_VALUE indicates that no current EA version is compatible with Graal. // Note: Keep README.md in sync with the EA version support checked here. @@ -138,8 +138,6 @@ class JVMCIVersionCheck { if (build >= JVMCI9_MIN_EA_BUILD) { return; } - // Using Object.equals suppresses Eclipse's "Dead code" warning. - // Unfortunately @SuppressWarnings("unused") can only be applied at method level. if (Objects.equals(JVMCI9_MIN_EA_BUILD, Integer.MAX_VALUE)) { failVersionCheck(exitOnFailure, "This version of Graal is not compatible with any JDK 9 Early Access build.%n"); } else { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/NodeCostDumpUtil.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/NodeCostDumpUtil.java new file mode 100644 index 00000000000..ad48b0e2956 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/NodeCostDumpUtil.java @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; +import java.util.stream.Collectors; + +import org.graalvm.compiler.debug.CSVUtil; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.spi.Canonicalizable; +import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; +import org.graalvm.compiler.nodes.spi.Virtualizable; + +public class NodeCostDumpUtil { + + private static final String prefix1 = "com.oracle."; + private static final String prefix2 = "org.graalvm."; + private static final String FMT = CSVUtil.buildFormatString("%s", "%s", "%s", "%s", "%s", "%s", "%s", "%s"); + + private static String getArgumentRegex(String arg) { + if (arg.length() == 0) { + return null; + } + try { + Pattern.compile(arg); + return arg; + } catch (PatternSyntaxException e) { + // silently ignore + System.err.println("Invalid regex given, defaulting to \".*\" regex.."); + return null; + } + } + + public static void main(String[] args) { + if (args.length != 1) { + System.err.println("NodeCostDumpUtil expects exactly one argument, the node name regex to match against."); + System.exit(-1); + } + final String pattern = getArgumentRegex(args[0]); + String version = System.getProperty("java.specification.version"); + if (version.compareTo("1.9") >= 0) { + System.err.printf("NodeCostDumpUtil does not support JDK versions greater than 1.8, current version is %s.\n", version); + System.exit(-1); + } + String[] jvmciCP = System.getProperty("jvmci.class.path.append").split(File.pathSeparator); + String[] primarySuiteCP = System.getProperty("primary.suite.cp").split(File.pathSeparator); + ClassLoader applicationClassLoader = Thread.currentThread().getContextClassLoader(); + HashSet> classes = new HashSet<>(); + try { + Set uniquePaths = new HashSet<>(Arrays.asList(primarySuiteCP)); + uniquePaths.addAll(Arrays.asList(jvmciCP)); + for (String path : uniquePaths) { + if (new File(path).exists()) { + if (path.endsWith(".jar")) { + try (FileSystem jarFileSystem = FileSystems.newFileSystem(URI.create("jar:file:" + path), Collections.emptyMap())) { + initAllClasses(jarFileSystem.getPath("/"), applicationClassLoader, classes); + } + } else { + initAllClasses(FileSystems.getDefault().getPath(path), applicationClassLoader, classes); + } + } + } + } catch (IOException ex) { + GraalError.shouldNotReachHere(); + } + System.err.printf("Loaded %d classes...\n", classes.size()); + List> nodeClasses = new ArrayList<>(); + for (Class loaded : classes) { + if (Node.class.isAssignableFrom(loaded) && !loaded.isArray()) { + nodeClasses.add(loaded); + } + } + System.err.printf("Loaded %s node classes...\n", nodeClasses.size()); + List> nc = new ArrayList<>(); + for (Class nodeClass : nodeClasses) { + Field f; + try { + f = nodeClass.getField("TYPE"); + f.setAccessible(true); + Object val = f.get(null); + NodeClass nodeType = (NodeClass) val; + nc.add(nodeType); + } catch (Throwable t) { + // Silently ignore problems here + } + } + System.err.printf("Read TYPE field from %s node classes...\n", nc.size()); + nc = nc.stream().filter(x -> x != null).collect(Collectors.toList()); + nc.sort((x, y) -> { + String a = x.getJavaClass().getName(); + String b = y.getJavaClass().getName(); + return a.compareTo(b); + }); + CSVUtil.Escape.println(System.out, FMT, "NodeName", "Size", "Overrides Size Method", "Cycles", "Overrides Cycles Method", "Canonicalizable", "MemoryCheckPoint", "Virtualizable"); + for (NodeClass nodeclass : nc) { + String packageStrippedName = null; + try { + packageStrippedName = nodeclass.getJavaClass().getCanonicalName().replace(prefix1, "").replace(prefix2, ""); + } catch (Throwable t) { + // do nothing + continue; + } + if (pattern != null && !packageStrippedName.matches(pattern)) { + continue; + } + boolean overridesSizeMethod = false; + boolean overridesCyclesMethod = false; + Class c = nodeclass.getJavaClass(); + try { + c.getDeclaredMethod("estimatedNodeSize"); + overridesSizeMethod = true; + } catch (Throwable t) { + // do nothing + } + try { + c.getDeclaredMethod("estimatedNodeCycles"); + overridesCyclesMethod = true; + } catch (Throwable t) { + // do nothing + } + CSVUtil.Escape.println(System.out, FMT, packageStrippedName, nodeclass.size(), overridesSizeMethod, nodeclass.cycles(), overridesCyclesMethod, canonicalizable(c), memoryCheckPoint(c), + virtualizable(c)); + } + } + + private static boolean canonicalizable(Class c) { + return Canonicalizable.class.isAssignableFrom(c); + } + + private static boolean virtualizable(Class c) { + return Virtualizable.class.isAssignableFrom(c); + } + + private static boolean memoryCheckPoint(Class c) { + return MemoryCheckpoint.class.isAssignableFrom(c); + } + + private static void initAllClasses(final Path root, ClassLoader classLoader, HashSet> classes) { + try { + Files.walkFileTree(root, new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + String className = root.relativize(file).toString(); + ClassLoader c = classLoader; + if (className.endsWith(".class")) { + String prefix = prefixed(className); + if (prefix != null) { + String stripped = stripClassName(className); + c = new URLClassLoader(new URL[]{new File(constructURLPart(stripped, className, prefix)).toURI().toURL()}, classLoader); + className = constructClazzPart(stripped, prefix); + } else { + String clazzPart = className.replace('/', '.'); + className = clazzPart.substring(0, clazzPart.length() - ".class".length()); + } + try { + Class systemClass = Class.forName(className, false, c); + if (systemClass.getEnclosingClass() != null) { + try { + classes.add(systemClass.getEnclosingClass()); + } catch (Throwable t) { + // do nothing + } + } + classes.add(systemClass); + } catch (Throwable ignored) { + } + } + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException ex) { + GraalError.shouldNotReachHere(); + } + } + + private static String prefixed(String className) { + if (className.contains(prefix1) && className.indexOf(prefix1) > 0) { + return prefix1; + } else if (className.contains(prefix2) && className.indexOf(prefix2) > 0) { + return prefix2; + } + return null; + } + + private static String stripClassName(String className) { + return className.replace('/', '.'); + } + + private static String constructClazzPart(String stripped, String prefix) { + String clazzPart = stripped.substring(stripped.lastIndexOf(prefix), stripped.length()); + return clazzPart.substring(0, clazzPart.length() - ".class".length()); + } + + private static String constructURLPart(String stripped, String className, String prefix) { + return className.substring(0, stripped.lastIndexOf(prefix)); + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOption.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java similarity index 57% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOption.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java index e2b389f8b96..ca4cb8bced1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOption.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java @@ -27,11 +27,9 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; -import java.lang.management.ManagementFactory; -import java.lang.management.RuntimeMXBean; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.UniquePathUtilities; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; @@ -39,35 +37,23 @@ import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; /** * An option that encapsulates and configures a print stream. */ -public class PrintStreamOption extends OptionValue { +public class PrintStreamOptionKey extends OptionKey { - public PrintStreamOption() { + public PrintStreamOptionKey() { super(null); } /** - * The print stream to which output will be written. - * - * Declared {@code volatile} to enable safe use of double-checked locking in - * {@link #getStream()} and {@link #setValue(Object)}. - */ - private volatile PrintStream ps; - - /** - * Replaces any instance of %p with an identifying name such as a process ID extracted from - * {@link RuntimeMXBean#getName()} and any instance of %t with the value of - * {@link System#currentTimeMillis()}. + * Replace any instance of %p with an identifying name. Try to get it from the RuntimeMXBean + * name. * * @return the name of the file to log to */ - private String getFilename() { - String name = getValue(); - if (name.contains("%t")) { - name = name.replaceAll("%t", String.valueOf(UniquePathUtilities.getGlobalTimeStamp())); - } + private String getFilename(OptionValues options) { + String name = getValue(options); if (name.contains("%p")) { - String runtimeName = ManagementFactory.getRuntimeMXBean().getName(); try { + String runtimeName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName(); int index = runtimeName.indexOf('@'); if (index != -1) { long pid = Long.parseLong(runtimeName.substring(0, index)); @@ -76,8 +62,13 @@ public class PrintStreamOption extends OptionValue { name = name.replaceAll("%p", runtimeName); } catch (NumberFormatException e) { + } catch (LinkageError err) { + name = String.valueOf(org.graalvm.compiler.debug.PathUtilities.getGlobalTimeStamp()); } } + if (name.contains("%t")) { + name = name.replaceAll("%t", String.valueOf(System.currentTimeMillis())); + } return name; } @@ -126,45 +117,26 @@ public class PrintStreamOption extends OptionValue { * Gets the print stream configured by this option. If no file is configured, the print stream * will output to HotSpot's {@link HotSpotJVMCIRuntimeProvider#getLogStream() log} stream. */ - public PrintStream getStream() { - if (ps == null) { - if (getValue() != null) { - synchronized (this) { - if (ps == null) { - try { - final boolean enableAutoflush = true; - ps = new PrintStream(new FileOutputStream(getFilename()), enableAutoflush); - /* - * Add the JVM and Java arguments to the log file to help identity it. - */ - String inputArguments = String.join(" ", ManagementFactory.getRuntimeMXBean().getInputArguments()); - ps.println("VM Arguments: " + inputArguments); - String cmd = System.getProperty("sun.java.command"); - if (cmd != null) { - ps.println("sun.java.command=" + cmd); - } - } catch (FileNotFoundException e) { - throw new RuntimeException("couldn't open file: " + getValue(), e); - } - } + public PrintStream getStream(OptionValues options) { + if (getValue(options) != null) { + try { + final boolean enableAutoflush = true; + PrintStream ps = new PrintStream(new FileOutputStream(getFilename(options)), enableAutoflush); + /* + * Add the JVM and Java arguments to the log file to help identity it. + */ + String inputArguments = String.join(" ", java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments()); + ps.println("VM Arguments: " + inputArguments); + String cmd = System.getProperty("sun.java.command"); + if (cmd != null) { + ps.println("sun.java.command=" + cmd); } - } else { - ps = new PrintStream(new DelayedOutputStream()); + return ps; + } catch (FileNotFoundException e) { + throw new RuntimeException("couldn't open file: " + getValue(options), e); } + } else { + return new PrintStream(new DelayedOutputStream()); } - return ps; - } - - @Override - public void setValue(Object v) { - if (ps != null) { - synchronized (this) { - if (ps != null) { - ps.close(); - ps = null; - } - } - } - super.setValue(v); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java index 700fa99e65f..04c1bb4857a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/debug/BenchmarkCounters.java @@ -22,11 +22,10 @@ */ package org.graalvm.compiler.hotspot.debug; -import java.io.FileNotFoundException; +import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; -import java.nio.file.Path; import java.util.Iterator; import java.util.Locale; import java.util.Map; @@ -39,17 +38,15 @@ import java.util.concurrent.atomic.AtomicLong; import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.debug.CSVUtil; -import org.graalvm.compiler.debug.GraalDebugConfig; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.TTY; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions; import org.graalvm.compiler.nodes.debug.DynamicCounterNode; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; -import org.graalvm.compiler.options.UniquePathUtilities; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -93,26 +90,26 @@ public class BenchmarkCounters { //@formatter:off @Option(help = "Turn on the benchmark counters, and displays the results on VM shutdown", type = OptionType.Debug) - public static final OptionValue GenericDynamicCounters = new OptionValue<>(false); + public static final OptionKey GenericDynamicCounters = new OptionKey<>(false); @Option(help = "Turn on the benchmark counters, and displays the results every n milliseconds", type = OptionType.Debug) - public static final OptionValue TimedDynamicCounters = new OptionValue<>(-1); + public static final OptionKey TimedDynamicCounters = new OptionKey<>(-1); @Option(help = "Turn on the benchmark counters, and listen for specific patterns on System.out/System.err:%n" + "Format: (err|out),start pattern,end pattern (~ matches multiple digits)%n" + "Examples:%n" + " dacapo = 'err, starting =====, PASSED in'%n" + " specjvm2008 = 'out,Iteration ~ (~s) begins:,Iteration ~ (~s) ends:'", type = OptionType.Debug) - public static final OptionValue BenchmarkDynamicCounters = new OptionValue<>(null); + public static final OptionKey BenchmarkDynamicCounters = new OptionKey<>(null); @Option(help = "Use grouping separators for number printing", type = OptionType.Debug) - public static final OptionValue DynamicCountersPrintGroupSeparator = new OptionValue<>(true); - @Option(help = "Print in human readable format", type = OptionType.Debug) - public static final OptionValue DynamicCountersHumanReadable = new OptionValue<>(true); - @Option(help = "Benchmark counters log file (default is stdout)", type = OptionType.Debug) - public static final OptionValue BenchmarkCountersFile = new OptionValue<>(null); + public static final OptionKey DynamicCountersPrintGroupSeparator = new OptionKey<>(true); + @Option(help = "File to which benchmark counters are dumped. A CSV format is used if the file ends with .csv " + + "otherwise a more human readable format is used. The fields in the CSV format are: " + + "category, group, name, value", type = OptionType.Debug) + public static final OptionKey BenchmarkCountersFile = new OptionKey<>(null); @Option(help = "Dump dynamic counters", type = OptionType.Debug) - public static final StableOptionValue BenchmarkCountersDumpDynamic = new StableOptionValue<>(true); + public static final OptionKey BenchmarkCountersDumpDynamic = new OptionKey<>(true); @Option(help = "Dump static counters", type = OptionType.Debug) - public static final StableOptionValue BenchmarkCountersDumpStatic = new StableOptionValue<>(false); + public static final OptionKey BenchmarkCountersDumpStatic = new OptionKey<>(false); //@formatter:on } @@ -168,113 +165,155 @@ public class BenchmarkCounters { return counter; } - private static synchronized void dump(PrintStream out, double seconds, long[] counters, int maxRows) { + private static synchronized void dump(OptionValues options, PrintStream out, double seconds, long[] counters, int maxRows) { if (!counterMap.isEmpty()) { - if (Options.DynamicCountersHumanReadable.getValue()) { - out.println("====== dynamic counters (" + counterMap.size() + " in total) ======"); - } - TreeSet set = new TreeSet<>(); - counterMap.forEach((nameGroup, counter) -> set.add(counter.group)); - for (String group : set) { - if (group != null) { - if (Options.BenchmarkCountersDumpStatic.getValue()) { - dumpCounters(out, seconds, counters, true, group, maxRows); - } - if (Options.BenchmarkCountersDumpDynamic.getValue()) { - dumpCounters(out, seconds, counters, false, group, maxRows); + try (Dumper dumper = Dumper.getDumper(options, out, counterMap.size(), seconds, maxRows)) { + TreeSet set = new TreeSet<>(); + counterMap.forEach((nameGroup, counter) -> set.add(counter.group)); + for (String group : set) { + if (group != null) { + if (Options.BenchmarkCountersDumpStatic.getValue(options)) { + dumper.dumpCounters(true, group, collectStaticCounters(), counterMap.entrySet(), options); + } + if (Options.BenchmarkCountersDumpDynamic.getValue(options)) { + dumper.dumpCounters(false, group, collectDynamicCounters(counters), counterMap.entrySet(), options); + } } } } - if (Options.DynamicCountersHumanReadable.getValue()) { - out.println("============================"); - } clear(counters); } } + private static synchronized long[] collectDynamicCounters(long[] counters) { + long[] array = counters.clone(); + for (int i = 0; i < array.length; i++) { + array[i] -= delta[i]; + } + return array; + } + + private static synchronized long[] collectStaticCounters() { + long[] array = new long[counterMap.size()]; + for (Counter counter : counterMap.values()) { + array[counter.index] = counter.staticCounters.get(); + } + return array; + } + private static synchronized void clear(long[] counters) { delta = counters; } - private static synchronized void dumpCounters(PrintStream out, double seconds, long[] counters, boolean staticCounter, String group, int maxRows) { + private static boolean shouldDumpComputerReadable(OptionValues options) { + String dumpFile = Options.BenchmarkCountersFile.getValue(options); + return dumpFile != null && (dumpFile.endsWith(".csv") || dumpFile.endsWith(".CSV")); + } - // collect the numbers - long[] array; - if (staticCounter) { - array = new long[counterMap.size()]; - for (Counter counter : counterMap.values()) { - array[counter.index] = counter.staticCounters.get(); - } - } else { - array = counters.clone(); - for (int i = 0; i < array.length; i++) { - array[i] -= delta[i]; - } + private abstract static class Dumper implements AutoCloseable { + public static Dumper getDumper(OptionValues options, PrintStream out, int counterSize, double second, int maxRows) { + Dumper dumper = shouldDumpComputerReadable(options) ? new ComputerReadableDumper(out) : new HumanReadableDumper(out, second, maxRows); + dumper.start(counterSize); + return dumper; } - Set> counterEntrySet = counterMap.entrySet(); - if (Options.DynamicCountersHumanReadable.getValue()) { - dumpHumanReadable(out, seconds, staticCounter, group, maxRows, array, counterEntrySet); - } else { - dumpComputerReadable(out, staticCounter, group, array, counterEntrySet); + + protected final PrintStream out; + + private Dumper(PrintStream out) { + this.out = out; } + + protected abstract void start(int size); + + public abstract void dumpCounters(boolean staticCounter, String group, long[] array, Set> counterEntrySet, OptionValues options); + + @Override + public abstract void close(); + } private static String getName(String nameGroup, String group) { return nameGroup.substring(0, nameGroup.length() - group.length() - 1); } - private static void dumpHumanReadable(PrintStream out, double seconds, boolean staticCounter, String group, int maxRows, long[] array, Set> counterEntrySet) { - // sort the counters by putting them into a sorted map - TreeMap sorted = new TreeMap<>(); - long sum = 0; - for (Map.Entry entry : counterEntrySet) { - Counter counter = entry.getValue(); - int index = counter.index; - if (counter.group.equals(group)) { - sum += array[index]; - sorted.put(array[index] * array.length + index, getName(entry.getKey(), group)); - } + private static long percentage(long counter, long sum) { + return (counter * 200 + 1) / sum / 2; + } + + private static class HumanReadableDumper extends Dumper { + private final double seconds; + private final int maxRows; + + HumanReadableDumper(PrintStream out, double seconds, int maxRows) { + super(out); + this.seconds = seconds; + this.maxRows = maxRows; } - if (sum > 0) { - long cutoff = sorted.size() < 10 ? 1 : Math.max(1, sum / 100); - int cnt = sorted.size(); + @Override + public void start(int size) { + out.println("====== dynamic counters (" + size + " in total) ======"); + } - // remove everything below cutoff and keep at most maxRows - Iterator> iter = sorted.entrySet().iterator(); - while (iter.hasNext()) { - Map.Entry entry = iter.next(); - long counter = entry.getKey() / array.length; - if (counter < cutoff || cnt > maxRows) { - iter.remove(); + @Override + public void close() { + out.println("============================"); + } + + @Override + public void dumpCounters(boolean staticCounter, String group, long[] array, Set> counterEntrySet, OptionValues options) { + // sort the counters by putting them into a sorted map + TreeMap sorted = new TreeMap<>(); + long sum = 0; + for (Map.Entry entry : counterEntrySet) { + Counter counter = entry.getValue(); + int index = counter.index; + if (counter.group.equals(group)) { + sum += array[index]; + sorted.put(array[index] * array.length + index, getName(entry.getKey(), group)); } - cnt--; } - String numFmt = Options.DynamicCountersPrintGroupSeparator.getValue() ? "%,19d" : "%19d"; - if (staticCounter) { - out.println("=========== " + group + " (static counters):"); - for (Map.Entry entry : sorted.entrySet()) { + if (sum > 0) { + long cutoff = sorted.size() < 10 ? 1 : Math.max(1, sum / 100); + int cnt = sorted.size(); + + // remove everything below cutoff and keep at most maxRows + Iterator> iter = sorted.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = iter.next(); long counter = entry.getKey() / array.length; - out.format(Locale.US, numFmt + " %3d%% %s\n", counter, percentage(counter, sum), entry.getValue()); - } - out.format(Locale.US, numFmt + " total\n", sum); - } else { - if (group.startsWith("~")) { - out.println("=========== " + group + " (dynamic counters), time = " + seconds + " s:"); - for (Map.Entry entry : sorted.entrySet()) { - long counter = entry.getKey() / array.length; - out.format(Locale.US, numFmt + "/s %3d%% %s\n", (long) (counter / seconds), percentage(counter, sum), entry.getValue()); + if (counter < cutoff || cnt > maxRows) { + iter.remove(); } - out.format(Locale.US, numFmt + "/s total\n", (long) (sum / seconds)); - } else { - out.println("=========== " + group + " (dynamic counters):"); + cnt--; + } + + String numFmt = Options.DynamicCountersPrintGroupSeparator.getValue(options) ? "%,19d" : "%19d"; + if (staticCounter) { + out.println("=========== " + group + " (static counters):"); for (Map.Entry entry : sorted.entrySet()) { long counter = entry.getKey() / array.length; out.format(Locale.US, numFmt + " %3d%% %s\n", counter, percentage(counter, sum), entry.getValue()); } out.format(Locale.US, numFmt + " total\n", sum); + } else { + if (group.startsWith("~")) { + out.println("=========== " + group + " (dynamic counters), time = " + seconds + " s:"); + for (Map.Entry entry : sorted.entrySet()) { + long counter = entry.getKey() / array.length; + out.format(Locale.US, numFmt + "/s %3d%% %s\n", (long) (counter / seconds), percentage(counter, sum), entry.getValue()); + } + out.format(Locale.US, numFmt + "/s total\n", (long) (sum / seconds)); + } else { + out.println("=========== " + group + " (dynamic counters):"); + for (Map.Entry entry : sorted.entrySet()) { + long counter = entry.getKey() / array.length; + out.format(Locale.US, numFmt + " %3d%% %s\n", counter, percentage(counter, sum), entry.getValue()); + } + out.format(Locale.US, numFmt + " total\n", sum); + } } } } @@ -282,23 +321,37 @@ public class BenchmarkCounters { private static final String CSV_FMT = CSVUtil.buildFormatString("%s", "%s", "%s", "%d"); - private static void dumpComputerReadable(PrintStream out, boolean staticCounter, String group, long[] array, Set> counterEntrySet) { - String category = staticCounter ? "static counters" : "dynamic counters"; - for (Map.Entry entry : counterEntrySet) { - Counter counter = entry.getValue(); - if (counter.group.equals(group)) { - String name = getName(entry.getKey(), group); - int index = counter.index; - long value = array[index]; - CSVUtil.Escape.println(out, CSV_FMT, category, group, name, value); + private static class ComputerReadableDumper extends Dumper { + + ComputerReadableDumper(PrintStream out) { + super(out); + } + + @Override + public void start(int size) { + // do nothing + } + + @Override + public void close() { + // do nothing + } + + @Override + public void dumpCounters(boolean staticCounter, String group, long[] array, Set> counterEntrySet, OptionValues options) { + String category = staticCounter ? "static counters" : "dynamic counters"; + for (Map.Entry entry : counterEntrySet) { + Counter counter = entry.getValue(); + if (counter.group.equals(group)) { + String name = getName(entry.getKey(), group); + int index = counter.index; + long value = array[index]; + CSVUtil.Escape.println(out, CSV_FMT, category, group, name, value); + } } } } - private static long percentage(long counter, long sum) { - return (counter * 200 + 1) / sum / 2; - } - private abstract static class CallbackOutputStream extends OutputStream { protected final PrintStream delegate; @@ -348,7 +401,7 @@ public class BenchmarkCounters { } } - public static void initialize(final HotSpotJVMCIRuntime jvmciRuntime) { + public static void initialize(final HotSpotJVMCIRuntime jvmciRuntime, OptionValues options) { final class BenchmarkCountersOutputStream extends CallbackOutputStream { private long startTime; @@ -376,15 +429,15 @@ public class BenchmarkCounters { if (waitingForEnd) { waitingForEnd = false; running = false; - BenchmarkCounters.dump(getPrintStream(), (System.nanoTime() - startTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); + BenchmarkCounters.dump(options, getPrintStream(options), (System.nanoTime() - startTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); } break; } } } - if (Options.BenchmarkDynamicCounters.getValue() != null) { - String[] arguments = Options.BenchmarkDynamicCounters.getValue().split(","); + if (Options.BenchmarkDynamicCounters.getValue(options) != null) { + String[] arguments = Options.BenchmarkDynamicCounters.getValue(options).split(","); if (arguments.length == 0 || (arguments.length % 3) != 0) { throw new GraalError("invalid arguments to BenchmarkDynamicCounters: (err|out),start,end,(err|out),start,end,... (~ matches multiple digits)"); } @@ -399,23 +452,23 @@ public class BenchmarkCounters { } enabled = true; } - if (Options.GenericDynamicCounters.getValue()) { + if (Options.GenericDynamicCounters.getValue(options)) { enabled = true; } - if (Options.TimedDynamicCounters.getValue() > 0) { + if (Options.TimedDynamicCounters.getValue(options) > 0) { Thread thread = new Thread() { long lastTime = System.nanoTime(); - PrintStream out = getPrintStream(); + PrintStream out = getPrintStream(options); @Override public void run() { while (true) { try { - Thread.sleep(Options.TimedDynamicCounters.getValue()); + Thread.sleep(Options.TimedDynamicCounters.getValue(options)); } catch (InterruptedException e) { } long time = System.nanoTime(); - dump(out, (time - lastTime) / 1000000000d, jvmciRuntime.collectCounters(), 10); + dump(options, out, (time - lastTime) / 1000000000d, jvmciRuntime.collectCounters(), 10); lastTime = time; } } @@ -430,19 +483,20 @@ public class BenchmarkCounters { } } - public static void shutdown(HotSpotJVMCIRuntime jvmciRuntime, long compilerStartTime) { - if (Options.GenericDynamicCounters.getValue()) { - dump(getPrintStream(), (System.nanoTime() - compilerStartTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); + public static void shutdown(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options, long compilerStartTime) { + if (Options.GenericDynamicCounters.getValue(options)) { + dump(options, getPrintStream(options), (System.nanoTime() - compilerStartTime) / 1000000000d, jvmciRuntime.collectCounters(), 100); } } - private static PrintStream getPrintStream() { - if (Options.BenchmarkCountersFile.getValue() != null) { + private static PrintStream getPrintStream(OptionValues options) { + if (Options.BenchmarkCountersFile.getValue(options) != null) { try { - Path path = UniquePathUtilities.getPathGlobal(Options.BenchmarkCountersFile, GraalDebugConfig.Options.DumpPath, "csv"); - TTY.println("Writing benchmark counters to '%s'", path); - return new PrintStream(path.toFile()); - } catch (FileNotFoundException e) { + + File file = new File(Options.BenchmarkCountersFile.getValue(options)); + TTY.println("Writing benchmark counters to '%s'", file.getAbsolutePath()); + return new PrintStream(file); + } catch (IOException e) { TTY.out().println(e.getMessage()); TTY.out().println("Fallback to default"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/HotSpotZapRegistersPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/HotSpotZapRegistersPhase.java index 39095452731..545c91d8af7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/HotSpotZapRegistersPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/lir/HotSpotZapRegistersPhase.java @@ -27,7 +27,7 @@ import static jdk.vm.ci.code.ValueUtil.isStackSlot; import java.util.ArrayList; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.hotspot.HotSpotLIRGenerationResult; import org.graalvm.compiler.hotspot.stubs.Stub; @@ -82,7 +82,8 @@ public final class HotSpotZapRegistersPhase extends PostAllocationOptimizationPh @SuppressWarnings("try") private static void processBlock(DiagnosticLIRGeneratorTool diagnosticLirGenTool, HotSpotLIRGenerationResult res, LIR lir, LIRInsertionBuffer buffer, AbstractBlockBase block, boolean zapRegisters, boolean zapStack) { - try (Indent indent = Debug.logAndIndent("Process block %s", block)) { + DebugContext debug = lir.getDebug(); + try (Indent indent = debug.logAndIndent("Process block %s", block)) { ArrayList instructions = lir.getLIRforBlock(block); buffer.init(instructions); for (int index = 0; index < instructions.size(); index++) { @@ -100,7 +101,7 @@ public final class HotSpotZapRegistersPhase extends PostAllocationOptimizationPh SaveRegistersOp old = res.getCalleeSaveInfo().put(state, zap); assert old == null : "Already another SaveRegisterOp registered! " + old; buffer.append(index + 1, (LIRInstruction) zap); - Debug.log("Insert ZapRegister after %s", inst); + debug.log("Insert ZapRegister after %s", inst); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/AddressLoweringHotSpotSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/AddressLoweringHotSpotSuitesProvider.java new file mode 100644 index 00000000000..7ffe6632298 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/AddressLoweringHotSpotSuitesProvider.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.meta; + +import java.util.ListIterator; + +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.BasePhase; +import org.graalvm.compiler.phases.common.AddressLoweringPhase; +import org.graalvm.compiler.phases.common.ExpandLogicPhase; +import org.graalvm.compiler.phases.common.FixReadsPhase; +import org.graalvm.compiler.phases.tiers.LowTierContext; +import org.graalvm.compiler.phases.tiers.Suites; +import org.graalvm.compiler.phases.tiers.SuitesCreator; + +/** + * Subclass to factor out management of address lowering. + */ +public class AddressLoweringHotSpotSuitesProvider extends HotSpotSuitesProvider { + + private final AddressLoweringPhase.AddressLowering addressLowering; + + public AddressLoweringHotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, + AddressLoweringPhase.AddressLowering addressLowering) { + super(defaultSuitesCreator, config, runtime); + this.addressLowering = addressLowering; + } + + @Override + public Suites createSuites(OptionValues options) { + Suites suites = super.createSuites(options); + + ListIterator> findPhase = suites.getLowTier().findPhase(FixReadsPhase.class); + if (findPhase == null) { + findPhase = suites.getLowTier().findPhase(ExpandLogicPhase.class); + } + findPhase.add(new AddressLoweringPhase(addressLowering)); + + return suites; + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java index 47ed91d18b3..97a5c5b6e7d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java @@ -22,43 +22,40 @@ */ package org.graalvm.compiler.hotspot.meta; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; import static org.graalvm.compiler.core.common.GraalOptions.AlwaysInlineVTableStubs; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.InlineVTableStubs; import static org.graalvm.compiler.core.common.GraalOptions.OmitHotExceptionStacktrace; -import static org.graalvm.compiler.core.common.LocationIdentity.any; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_KLASS_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_HANDLE_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.COMPRESSED_HUB_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.DISPLACED_MARK_WORD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_WRITE_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.KLASS_LAYOUT_HELPER_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION; -import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.INIT_LOCATION; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static org.graalvm.word.LocationIdentity.any; import java.lang.ref.Reference; import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.LocationIdentity; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; -import org.graalvm.compiler.hotspot.nodes.CompressionNode.CompressionOp; -import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; -import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; +import org.graalvm.compiler.hotspot.nodes.BeginLockScopeNode; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier; @@ -66,13 +63,18 @@ import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier; import org.graalvm.compiler.hotspot.nodes.GetObjectAddressNode; +import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode; import org.graalvm.compiler.hotspot.nodes.HotSpotDirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.HotSpotIndirectCallTargetNode; import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier; import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; +import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; +import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; +import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; +import org.graalvm.compiler.hotspot.nodes.profiling.ProfileNode; +import org.graalvm.compiler.hotspot.nodes.type.HotSpotNarrowOopStamp; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.nodes.type.MethodPointerStamp; -import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp; import org.graalvm.compiler.hotspot.replacements.AssertionSnippets; import org.graalvm.compiler.hotspot.replacements.ClassGetHubNode; import org.graalvm.compiler.hotspot.replacements.HashCodeSnippets; @@ -96,13 +98,13 @@ import org.graalvm.compiler.hotspot.replacements.profiling.ProfileSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractDeoptimizeNode; +import org.graalvm.compiler.nodes.CompressionNode.CompressionOp; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.LoweredCallTargetNode; import org.graalvm.compiler.nodes.ParameterNode; -import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.SafepointNode; import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StructuredGraph; @@ -119,13 +121,14 @@ import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.GetClassNode; import org.graalvm.compiler.nodes.extended.GuardedUnsafeLoadNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode; import org.graalvm.compiler.nodes.extended.OSRLocalNode; +import org.graalvm.compiler.nodes.extended.OSRLockNode; +import org.graalvm.compiler.nodes.extended.OSRMonitorEnterNode; import org.graalvm.compiler.nodes.extended.OSRStartNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.extended.StoreHubNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; import org.graalvm.compiler.nodes.java.ClassIsAssignableFromNode; import org.graalvm.compiler.nodes.java.DynamicNewArrayNode; import org.graalvm.compiler.nodes.java.DynamicNewInstanceNode; @@ -134,6 +137,7 @@ import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.nodes.java.LoadExceptionObjectNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.java.MonitorExitNode; +import org.graalvm.compiler.nodes.java.MonitorIdNode; import org.graalvm.compiler.nodes.java.NewArrayNode; import org.graalvm.compiler.nodes.java.NewInstanceNode; import org.graalvm.compiler.nodes.java.NewMultiArrayNode; @@ -148,8 +152,10 @@ import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.DefaultJavaLoweringProvider; import org.graalvm.compiler.replacements.nodes.AssertionNode; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.hotspot.HotSpotCallingConventionType; @@ -194,25 +200,29 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } @Override - public void initialize(HotSpotProviders providers, GraalHotSpotVMConfig config) { - super.initialize(providers, providers.getSnippetReflection()); + public void initialize(OptionValues options, Iterable factories, HotSpotProviders providers, GraalHotSpotVMConfig config) { + super.initialize(options, factories, runtime, providers, providers.getSnippetReflection()); assert target == providers.getCodeCache().getTarget(); - instanceofSnippets = new InstanceOfSnippets.Templates(providers, target); - newObjectSnippets = new NewObjectSnippets.Templates(providers, target, config); - monitorSnippets = new MonitorSnippets.Templates(providers, target, config.useFastLocking); - writeBarrierSnippets = new WriteBarrierSnippets.Templates(providers, target, config.useCompressedOops ? config.getOopEncoding() : null); - exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(providers, target); - unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(providers, target); - assertionSnippets = new AssertionSnippets.Templates(providers, target); - arraycopySnippets = new ArrayCopySnippets.Templates(providers, target); - stringToBytesSnippets = new StringToBytesSnippets.Templates(providers, target); - hashCodeSnippets = new HashCodeSnippets.Templates(providers, target); - if (GeneratePIC.getValue()) { - resolveConstantSnippets = new ResolveConstantSnippets.Templates(providers, target); - profileSnippets = new ProfileSnippets.Templates(providers, target); + instanceofSnippets = new InstanceOfSnippets.Templates(options, factories, runtime, providers, target); + newObjectSnippets = new NewObjectSnippets.Templates(options, factories, runtime, providers, target, config); + monitorSnippets = new MonitorSnippets.Templates(options, factories, runtime, providers, target, config.useFastLocking); + writeBarrierSnippets = new WriteBarrierSnippets.Templates(options, factories, runtime, providers, target, config.useCompressedOops ? config.getOopEncoding() : null); + exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(options, factories, providers, target); + unsafeLoadSnippets = new UnsafeLoadSnippets.Templates(options, factories, providers, target); + assertionSnippets = new AssertionSnippets.Templates(options, factories, providers, target); + arraycopySnippets = new ArrayCopySnippets.Templates(options, factories, runtime, providers, target); + stringToBytesSnippets = new StringToBytesSnippets.Templates(options, factories, providers, target); + hashCodeSnippets = new HashCodeSnippets.Templates(options, factories, providers, target); + if (GeneratePIC.getValue(options)) { + resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, factories, providers, target); + profileSnippets = new ProfileSnippets.Templates(options, factories, providers, target); } - providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(providers, target)); + providers.getReplacements().registerSnippetTemplateCache(new UnsafeArrayCopySnippets.Templates(options, factories, providers, target)); + } + + public MonitorSnippets.Templates getMonitorSnippets() { + return monitorSnippets; } @Override @@ -303,7 +313,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } } else if (n instanceof MonitorExitNode) { if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - monitorSnippets.lower((MonitorExitNode) n, tool); + monitorSnippets.lower((MonitorExitNode) n, registers, tool); } } else if (n instanceof ArrayCopyNode) { arraycopySnippets.lower((ArrayCopyNode) n, tool); @@ -355,11 +365,17 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } else if (n instanceof IdentityHashCodeNode) { hashCodeSnippets.lower((IdentityHashCodeNode) n, tool); } else if (n instanceof ResolveConstantNode) { - resolveConstantSnippets.lower((ResolveConstantNode) n, tool); + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + resolveConstantSnippets.lower((ResolveConstantNode) n, tool); + } } else if (n instanceof ResolveMethodAndLoadCountersNode) { - resolveConstantSnippets.lower((ResolveMethodAndLoadCountersNode) n, tool); + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + resolveConstantSnippets.lower((ResolveMethodAndLoadCountersNode) n, tool); + } } else if (n instanceof InitializeKlassNode) { - resolveConstantSnippets.lower((InitializeKlassNode) n, tool); + if (graph.getGuardsStage().areFrameStatesAtDeopts()) { + resolveConstantSnippets.lower((InitializeKlassNode) n, tool); + } } else if (n instanceof ProfileNode) { profileSnippets.lower((ProfileNode) n, tool); } else { @@ -395,7 +411,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider StructuredGraph graph = n.graph(); assert !n.getHub().isConstant(); AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getVMConfig().klassLayoutHelperOffset); - n.replaceAtUsagesAndDelete(graph.unique(new FloatingReadNode(address, KLASS_LAYOUT_HELPER_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE))); + n.replaceAtUsagesAndDelete(graph.unique(new FloatingReadNode(address, KLASS_LAYOUT_HELPER_LOCATION, null, n.stamp(), null, BarrierType.NONE))); } private void lowerHubGetClassNode(HubGetClassNode n, LoweringTool tool) { @@ -403,10 +419,17 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider return; } + ValueNode hub = n.getHub(); + GraalHotSpotVMConfig vmConfig = runtime.getVMConfig(); StructuredGraph graph = n.graph(); - assert !n.getHub().isConstant(); - AddressNode address = createOffsetAddress(graph, n.getHub(), runtime.getVMConfig().classMirrorOffset); - FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE)); + assert !hub.isConstant() || GraalOptions.ImmutableCode.getValue(graph.getOptions()); + AddressNode mirrorAddress = createOffsetAddress(graph, hub, vmConfig.classMirrorOffset); + FloatingReadNode read = graph.unique(new FloatingReadNode(mirrorAddress, CLASS_MIRROR_LOCATION, null, vmConfig.classMirrorIsHandle ? StampFactory.forKind(target.wordJavaKind) : n.stamp(), + null, BarrierType.NONE)); + if (vmConfig.classMirrorIsHandle) { + AddressNode address = createOffsetAddress(graph, read, 0); + read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_HANDLE_LOCATION, null, n.stamp(), null, BarrierType.NONE)); + } n.replaceAtUsagesAndDelete(read); } @@ -418,7 +441,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider StructuredGraph graph = n.graph(); assert !n.getValue().isConstant(); AddressNode address = createOffsetAddress(graph, n.getValue(), runtime.getVMConfig().klassOffset); - FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_KLASS_LOCATION, null, n.stamp(), n.getGuard(), BarrierType.NONE)); + FloatingReadNode read = graph.unique(new FloatingReadNode(address, CLASS_KLASS_LOCATION, null, n.stamp(), null, BarrierType.NONE)); n.replaceAtUsagesAndDelete(read); } @@ -428,15 +451,15 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider NodeInputList parameters = callTarget.arguments(); ValueNode receiver = parameters.size() <= 0 ? null : parameters.get(0); if (!callTarget.isStatic() && receiver.stamp() instanceof ObjectStamp && !StampTool.isPointerNonNull(receiver)) { - GuardingNode receiverNullCheck = createNullCheck(receiver, invoke.asNode(), tool); - PiNode nonNullReceiver = graph.unique(new PiNode(receiver, ((ObjectStamp) receiver.stamp()).join(StampFactory.objectNonNull()), (ValueNode) receiverNullCheck)); + ValueNode nonNullReceiver = createNullCheckedValue(receiver, invoke.asNode(), tool); parameters.set(0, nonNullReceiver); receiver = nonNullReceiver; } JavaType[] signature = callTarget.targetMethod().getSignature().toParameterTypes(callTarget.isStatic() ? null : callTarget.targetMethod().getDeclaringClass()); LoweredCallTargetNode loweredCallTarget = null; - if (InlineVTableStubs.getValue() && callTarget.invokeKind().isIndirect() && (AlwaysInlineVTableStubs.getValue() || invoke.isPolymorphic())) { + OptionValues options = graph.getOptions(); + if (InlineVTableStubs.getValue(options) && callTarget.invokeKind().isIndirect() && (AlwaysInlineVTableStubs.getValue(options) || invoke.isPolymorphic())) { HotSpotResolvedJavaMethod hsMethod = (HotSpotResolvedJavaMethod) callTarget.targetMethod(); ResolvedJavaType receiverType = invoke.getReceiverType(); if (hsMethod.isInVirtualMethodTable(receiverType)) { @@ -473,7 +496,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider @Override protected Stamp loadStamp(Stamp stamp, JavaKind kind, boolean compressible) { if (kind == JavaKind.Object && compressible && runtime.getVMConfig().useCompressedOops) { - return NarrowOopStamp.compressed((ObjectStamp) stamp, runtime.getVMConfig().getOopEncoding()); + return HotSpotNarrowOopStamp.compressed((ObjectStamp) stamp, runtime.getVMConfig().getOopEncoding()); } return super.loadStamp(stamp, kind, compressible); } @@ -481,7 +504,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider @Override protected ValueNode implicitLoadConvert(JavaKind kind, ValueNode value, boolean compressible) { if (kind == JavaKind.Object && compressible && runtime.getVMConfig().useCompressedOops) { - return new CompressionNode(CompressionOp.Uncompress, value, runtime.getVMConfig().getOopEncoding()); + return new HotSpotCompressionNode(CompressionOp.Uncompress, value, runtime.getVMConfig().getOopEncoding()); } return super.implicitLoadConvert(kind, value, compressible); } @@ -496,7 +519,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider @Override protected ValueNode implicitStoreConvert(JavaKind kind, ValueNode value, boolean compressible) { if (kind == JavaKind.Object && compressible && runtime.getVMConfig().useCompressedOops) { - return new CompressionNode(CompressionOp.Compress, value, runtime.getVMConfig().getOopEncoding()); + return new HotSpotCompressionNode(CompressionOp.Compress, value, runtime.getVMConfig().getOopEncoding()); } return super.implicitStoreConvert(kind, value, compressible); } @@ -512,7 +535,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } @Override - protected void lowerUnsafeLoadNode(UnsafeLoadNode load, LoweringTool tool) { + protected void lowerUnsafeLoadNode(RawLoadNode load, LoweringTool tool) { StructuredGraph graph = load.graph(); if (!(load instanceof GuardedUnsafeLoadNode) && !graph.getGuardsStage().allowsFloatingGuards() && addReadBarrier(load)) { unsafeLoadSnippets.lower(load, tool); @@ -559,23 +582,64 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider ParameterNode buffer = graph.addWithoutUnique(new ParameterNode(0, StampPair.createSingle(StampFactory.forKind(runtime.getTarget().wordJavaKind)))); ForeignCallNode migrationEnd = graph.add(new ForeignCallNode(foreignCalls, OSR_MIGRATION_END, buffer)); migrationEnd.setStateAfter(osrStart.stateAfter()); - newStart.setNext(migrationEnd); FixedNode next = osrStart.next(); osrStart.setNext(null); migrationEnd.setNext(next); graph.setStart(newStart); - // mirroring the calculations in c1_GraphBuilder.cpp (setup_osr_entry_block) - int localsOffset = (graph.method().getMaxLocals() - 1) * 8; + final int wordSize = target.wordSize; + + // @formatter:off + // taken from c2 locals_addr = osr_buf + (max_locals-1)*wordSize) + // @formatter:on + int localsOffset = (graph.method().getMaxLocals() - 1) * wordSize; for (OSRLocalNode osrLocal : graph.getNodes(OSRLocalNode.TYPE)) { int size = osrLocal.getStackKind().getSlotCount(); - int offset = localsOffset - (osrLocal.index() + size - 1) * 8; + int offset = localsOffset - (osrLocal.index() + size - 1) * wordSize; AddressNode address = createOffsetAddress(graph, buffer, offset); ReadNode load = graph.add(new ReadNode(address, any(), osrLocal.stamp(), BarrierType.NONE)); osrLocal.replaceAndDelete(load); graph.addBeforeFixed(migrationEnd, load); } + + // @formatter:off + // taken from c2 monitors_addr = osr_buf + (max_locals+mcnt*2-1)*wordSize); + // @formatter:on + final int lockCount = osrStart.stateAfter().locksSize(); + final int locksOffset = (graph.method().getMaxLocals() + lockCount * 2 - 1) * wordSize; + + // first initialize the lock slots for all enters with the displaced marks read from the + // buffer + for (OSRMonitorEnterNode osrMonitorEnter : graph.getNodes(OSRMonitorEnterNode.TYPE)) { + MonitorIdNode monitorID = osrMonitorEnter.getMonitorId(); + OSRLockNode lock = (OSRLockNode) osrMonitorEnter.object(); + final int index = lock.index(); + + final int offsetDisplacedHeader = locksOffset - ((index * 2) + 1) * wordSize; + final int offsetLockObject = locksOffset - index * 2 * wordSize; + + // load the displaced mark from the osr buffer + AddressNode addressDisplacedHeader = createOffsetAddress(graph, buffer, offsetDisplacedHeader); + ReadNode loadDisplacedHeader = graph.add(new ReadNode(addressDisplacedHeader, any(), lock.stamp(), BarrierType.NONE)); + graph.addBeforeFixed(migrationEnd, loadDisplacedHeader); + + // we need to initialize the stack slot for the lock + BeginLockScopeNode beginLockScope = graph.add(new BeginLockScopeNode(lock.getStackKind(), monitorID.getLockDepth())); + graph.addBeforeFixed(migrationEnd, beginLockScope); + + // write the displaced mark to the correct stack slot + AddressNode addressDisplacedMark = createOffsetAddress(graph, beginLockScope, runtime.getVMConfig().basicLockDisplacedHeaderOffset); + WriteNode writeStackSlot = graph.add(new WriteNode(addressDisplacedMark, DISPLACED_MARK_WORD_LOCATION, loadDisplacedHeader, BarrierType.NONE)); + graph.addBeforeFixed(migrationEnd, writeStackSlot); + + // load the lock object from the osr buffer + AddressNode addressLockObject = createOffsetAddress(graph, buffer, offsetLockObject); + ReadNode loadObject = graph.add(new ReadNode(addressLockObject, any(), lock.stamp(), BarrierType.NONE)); + lock.replaceAndDelete(loadObject); + graph.addBeforeFixed(migrationEnd, loadObject); + } + osrStart.replaceAtUsagesAndDelete(newStart); } } @@ -616,7 +680,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider } private void lowerBytecodeExceptionNode(BytecodeExceptionNode node) { - if (OmitHotExceptionStacktrace.getValue()) { + if (OmitHotExceptionStacktrace.getValue(node.getOptions())) { if (throwCachedException(node)) { return; } @@ -640,7 +704,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider graph.replaceFixedWithFixed(node, foreignCallNode); } - private boolean addReadBarrier(UnsafeLoadNode load) { + private boolean addReadBarrier(RawLoadNode load) { if (runtime.getVMConfig().useG1GC && load.graph().getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS && load.object().getStackKind() == JavaKind.Object && load.accessKind() == JavaKind.Object && !StampTool.isPointerAlwaysNull(load.object())) { ResolvedJavaType type = StampTool.typeOrNull(load.object()); @@ -659,7 +723,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider assert vtableEntryOffset > 0; // We use LocationNode.ANY_LOCATION for the reads that access the vtable // entry as HotSpot does not guarantee that this is a final value. - Stamp methodStamp = MethodPointerStamp.method(); + Stamp methodStamp = MethodPointerStamp.methodNonNull(); AddressNode address = createOffsetAddress(graph, hub, vtableEntryOffset); ReadNode metaspaceMethod = graph.add(new ReadNode(address, any(), methodStamp, BarrierType.NONE)); return metaspaceMethod; @@ -681,7 +745,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider LocationIdentity hubLocation = runtime.getVMConfig().useCompressedClassPointers ? COMPRESSED_HUB_LOCATION : HUB_LOCATION; FloatingReadNode memoryRead = graph.unique(new FloatingReadNode(address, hubLocation, null, hubStamp, null, BarrierType.NONE)); if (runtime.getVMConfig().useCompressedClassPointers) { - return CompressionNode.uncompress(memoryRead, runtime.getVMConfig().getKlassEncoding()); + return HotSpotCompressionNode.uncompress(memoryRead, runtime.getVMConfig().getKlassEncoding()); } else { return memoryRead; } @@ -692,7 +756,7 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider ValueNode writeValue = value; if (runtime.getVMConfig().useCompressedClassPointers) { - writeValue = CompressionNode.compress(value, runtime.getVMConfig().getKlassEncoding()); + writeValue = HotSpotCompressionNode.compress(value, runtime.getVMConfig().getKlassEncoding()); } AddressNode address = createOffsetAddress(graph, object, runtime.getVMConfig().hubOffset); @@ -734,9 +798,4 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider public int arrayLengthOffset() { return runtime.getVMConfig().arrayOopDescLengthOffset(); } - - @Override - public LocationIdentity initLocationIdentity() { - return INIT_LOCATION; - } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java index ec7de3fad23..2ef16f9274a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotAOTProfilingPlugin.java @@ -22,11 +22,11 @@ */ package org.graalvm.compiler.hotspot.meta; -import org.graalvm.compiler.hotspot.FingerprintUtil; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -34,46 +34,46 @@ import jdk.vm.ci.meta.ResolvedJavaMethod; public class HotSpotAOTProfilingPlugin extends HotSpotProfilingPlugin { public static class Options { @Option(help = "Do profiling and callbacks to tiered runtime", type = OptionType.User)// - public static final OptionValue TieredAOT = new OptionValue<>(false); + public static final OptionKey TieredAOT = new OptionKey<>(false); @Option(help = "Invocation notification frequency", type = OptionType.Expert)// - public static final OptionValue TierAInvokeNotifyFreqLog = new OptionValue<>(13); + public static final OptionKey TierAInvokeNotifyFreqLog = new OptionKey<>(13); @Option(help = "Inlinee invocation notification frequency (-1 means count, but do not notify)", type = OptionType.Expert)// - public static final OptionValue TierAInvokeInlineeNotifyFreqLog = new OptionValue<>(-1); + public static final OptionKey TierAInvokeInlineeNotifyFreqLog = new OptionKey<>(-1); @Option(help = "Invocation profile probability", type = OptionType.Expert)// - public static final OptionValue TierAInvokeProfileProbabilityLog = new OptionValue<>(8); + public static final OptionKey TierAInvokeProfileProbabilityLog = new OptionKey<>(8); @Option(help = "Backedge notification frequency", type = OptionType.Expert)// - public static final OptionValue TierABackedgeNotifyFreqLog = new OptionValue<>(16); + public static final OptionKey TierABackedgeNotifyFreqLog = new OptionKey<>(16); @Option(help = "Backedge profile probability", type = OptionType.Expert)// - public static final OptionValue TierABackedgeProfileProbabilityLog = new OptionValue<>(12); + public static final OptionKey TierABackedgeProfileProbabilityLog = new OptionKey<>(12); } @Override public boolean shouldProfile(GraphBuilderContext builder, ResolvedJavaMethod method) { - return super.shouldProfile(builder, method) && FingerprintUtil.getFingerprint(((HotSpotResolvedObjectType) method.getDeclaringClass())) != 0; + return super.shouldProfile(builder, method) && ((HotSpotResolvedObjectType) method.getDeclaringClass()).getFingerprint() != 0; } @Override - public int invokeNotifyFreqLog() { - return Options.TierAInvokeNotifyFreqLog.getValue(); + public int invokeNotifyFreqLog(OptionValues options) { + return Options.TierAInvokeNotifyFreqLog.getValue(options); } @Override - public int invokeInlineeNotifyFreqLog() { - return Options.TierAInvokeInlineeNotifyFreqLog.getValue(); + public int invokeInlineeNotifyFreqLog(OptionValues options) { + return Options.TierAInvokeInlineeNotifyFreqLog.getValue(options); } @Override - public int invokeProfilePobabilityLog() { - return Options.TierAInvokeProfileProbabilityLog.getValue(); + public int invokeProfilePobabilityLog(OptionValues options) { + return Options.TierAInvokeProfileProbabilityLog.getValue(options); } @Override - public int backedgeNotifyFreqLog() { - return Options.TierABackedgeNotifyFreqLog.getValue(); + public int backedgeNotifyFreqLog(OptionValues options) { + return Options.TierABackedgeNotifyFreqLog.getValue(options); } @Override - public int backedgeProfilePobabilityLog() { - return Options.TierABackedgeProfileProbabilityLog.getValue(); + public int backedgeProfilePobabilityLog(OptionValues options) { + return Options.TierABackedgeProfileProbabilityLog.getValue(options); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotClassInitializationPlugin.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotClassInitializationPlugin.java index fa71a6adf18..f34dba44e97 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotClassInitializationPlugin.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotClassInitializationPlugin.java @@ -26,7 +26,9 @@ import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; +import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin; @@ -40,18 +42,24 @@ public final class HotSpotClassInitializationPlugin implements ClassInitializati @Override public boolean shouldApply(GraphBuilderContext builder, ResolvedJavaType type) { if (!builder.parsingIntrinsic()) { - ResolvedJavaMethod method = builder.getGraph().method(); - ResolvedJavaType methodHolder = method.getDeclaringClass(); - // We can elide initialization nodes if type >=: methodHolder. - // The type is already initialized by either "new" or "invokestatic". + if (!type.isArray()) { + ResolvedJavaMethod method = builder.getGraph().method(); + ResolvedJavaType methodHolder = method.getDeclaringClass(); + // We can elide initialization nodes if type >=: methodHolder. + // The type is already initialized by either "new" or "invokestatic". - // Emit initialization node if type is an interface since: - // JLS 12.4: Before a class is initialized, its direct superclass must be initialized, - // but interfaces implemented by the class are not initialized. - // and a class or interface type T will be initialized immediately - // before the first occurrence of accesses listed in JLS 12.4.1. + // Emit initialization node if type is an interface since: + // JLS 12.4: Before a class is initialized, its direct superclass must be + // initialized, but interfaces implemented by the class are not + // initialized and a class or interface type T will be initialized + // immediately before the first occurrence of accesses listed + // in JLS 12.4.1. - return !type.isAssignableFrom(methodHolder) || type.isInterface(); + return !type.isAssignableFrom(methodHolder) || type.isInterface(); + } else if (!type.getComponentType().isPrimitive()) { + // Always apply to object array types + return true; + } } return false; } @@ -61,8 +69,8 @@ public final class HotSpotClassInitializationPlugin implements ClassInitializati assert shouldApply(builder, type); Stamp hubStamp = builder.getStampProvider().createHubStamp((ObjectStamp) StampFactory.objectNonNull()); ConstantNode hub = builder.append(ConstantNode.forConstant(hubStamp, ((HotSpotResolvedObjectType) type).klass(), builder.getMetaAccess(), builder.getGraph())); - InitializeKlassNode initialize = builder.append(new InitializeKlassNode(hub)); - initialize.setStateBefore(frameState); - return initialize; + DeoptimizingFixedWithNextNode result = builder.append(type.isArray() ? new ResolveConstantNode(hub) : new InitializeKlassNode(hub)); + result.setStateBefore(frameState); + return result; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotConstantFieldProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotConstantFieldProvider.java index f7f99c64208..588982ebfb5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotConstantFieldProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotConstantFieldProvider.java @@ -24,6 +24,7 @@ package org.graalvm.compiler.hotspot.meta; import org.graalvm.compiler.core.common.spi.JavaConstantFieldProvider; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; import jdk.vm.ci.meta.MetaAccessProvider; @@ -47,7 +48,7 @@ public class HotSpotConstantFieldProvider extends JavaConstantFieldProvider { if (!config.foldStableValues) { return false; } - if (field.isStatic() && !isStaticFieldConstant(field)) { + if (field.isStatic() && !isStaticFieldConstant(field, tool.getOptions())) { return false; } @@ -59,7 +60,7 @@ public class HotSpotConstantFieldProvider extends JavaConstantFieldProvider { @Override protected boolean isFinalField(ResolvedJavaField field, ConstantFieldTool tool) { - if (field.isStatic() && !isStaticFieldConstant(field)) { + if (field.isStatic() && !isStaticFieldConstant(field, tool.getOptions())) { return false; } @@ -68,7 +69,7 @@ public class HotSpotConstantFieldProvider extends JavaConstantFieldProvider { private static final String SystemClassName = "Ljava/lang/System;"; - protected boolean isStaticFieldConstant(ResolvedJavaField field) { + protected boolean isStaticFieldConstant(ResolvedJavaField field, @SuppressWarnings("unused") OptionValues options) { ResolvedJavaType declaringClass = field.getDeclaringClass(); return declaringClass.isInitialized() && !declaringClass.getName().equals(SystemClassName); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProvider.java index 76b663c6b8b..e3a51de05c5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProvider.java @@ -22,7 +22,10 @@ */ package org.graalvm.compiler.hotspot.meta; +import java.util.List; + import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; +import org.graalvm.compiler.hotspot.stubs.Stub; import jdk.vm.ci.meta.Value; @@ -35,4 +38,9 @@ public interface HotSpotForeignCallsProvider extends ForeignCallsProvider { * Gets the registers that must be saved across a foreign call into the runtime. */ Value[] getNativeABICallerSaveRegisters(); + + /** + * Gets the set of stubs linked to by the foreign calls represented by this object. + */ + List getStubs(); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java index f2ddb967437..a396035ddcf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java @@ -22,16 +22,15 @@ */ package org.graalvm.compiler.hotspot.meta; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCall; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCallee; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect; @@ -40,8 +39,11 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.stubs.ForeignCallStub; import org.graalvm.compiler.hotspot.stubs.Stub; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordTypes; +import org.graalvm.util.EconomicMap; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.CodeCacheProvider; @@ -64,7 +66,7 @@ public abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignC protected final HotSpotJVMCIRuntimeProvider jvmciRuntime; protected final HotSpotGraalRuntimeProvider runtime; - protected final Map foreignCalls = new HashMap<>(); + protected final EconomicMap foreignCalls = EconomicMap.create(); protected final MetaAccessProvider metaAccess; protected final CodeCacheProvider codeCache; protected final WordTypes wordTypes; @@ -144,9 +146,9 @@ public abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignC * cannot be re-executed. * @param killedLocations the memory locations killed by the foreign call */ - public void linkForeignCall(HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, boolean reexecutable, + public void linkForeignCall(OptionValues options, HotSpotProviders providers, ForeignCallDescriptor descriptor, long address, boolean prependThread, Transition transition, boolean reexecutable, LocationIdentity... killedLocations) { - ForeignCallStub stub = new ForeignCallStub(jvmciRuntime, providers, address, descriptor, prependThread, transition, reexecutable, killedLocations); + ForeignCallStub stub = new ForeignCallStub(options, jvmciRuntime, providers, address, descriptor, prependThread, transition, reexecutable, killedLocations); HotSpotForeignCallLinkage linkage = stub.getLinkage(); HotSpotForeignCallLinkage targetLinkage = stub.getTargetLinkage(); linkage.setCompiledStub(stub); @@ -198,4 +200,17 @@ public abstract class HotSpotForeignCallsProviderImpl implements HotSpotForeignC public LIRKind getValueKind(JavaKind javaKind) { return LIRKind.fromJavaKind(codeCache.getTarget().arch, javaKind); } + + @Override + public List getStubs() { + List stubs = new ArrayList<>(); + for (HotSpotForeignCallLinkage linkage : foreignCalls.getValues()) { + if (linkage.isCompiledStub()) { + Stub stub = linkage.getStub(); + assert stub != null; + stubs.add(stub); + } + } + return stubs; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java index 659a79ee6d3..f9709bce633 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraalConstantFieldProvider.java @@ -23,8 +23,6 @@ package org.graalvm.compiler.hotspot.meta; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; -import static org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider.ImmutableCodeLazy.isCalledForSnippets; -import static org.graalvm.compiler.hotspot.stubs.SnippetStub.SnippetGraphUnderConstruction; import java.util.ArrayList; import java.util.List; @@ -32,18 +30,13 @@ import java.util.List; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.options.StableOptionValue; -import org.graalvm.compiler.replacements.ReplacementsImpl; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetCounter; -import org.graalvm.compiler.replacements.SnippetTemplate; -import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.runtime.JVMCI; /** * Extends {@link HotSpotConstantFieldProvider} to override the implementation of @@ -57,25 +50,55 @@ public class HotSpotGraalConstantFieldProvider extends HotSpotConstantFieldProvi } @Override - public T readConstantField(ResolvedJavaField field, ConstantFieldTool tool) { - assert !ImmutableCode.getValue() || isCalledForSnippets(metaAccess) || SnippetGraphUnderConstruction.get() != null || - FieldReadEnabledInImmutableCode.get() == Boolean.TRUE : tool.getReceiver(); - if (!field.isStatic() && field.getName().equals("value")) { - if (getStableOptionValueType().isInstance(tool.getReceiver())) { - JavaConstant ret = tool.readValue(); - return tool.foldConstant(ret); - } - } - - return super.readConstantField(field, tool); + protected boolean isStaticFieldConstant(ResolvedJavaField field, OptionValues options) { + return super.isStaticFieldConstant(field, options) && (!ImmutableCode.getValue(options) || isEmbeddableField(field)); } /** - * In AOT mode, some fields should never be embedded even for snippets/replacements. + * The set of fields whose values cannot be constant folded in ImmutableCode mode. This is + * volatile to support double-checked locking lazy initialization. */ - @Override - protected boolean isStaticFieldConstant(ResolvedJavaField field) { - return super.isStaticFieldConstant(field) && (!ImmutableCode.getValue() || ImmutableCodeLazy.isEmbeddable(field)); + private volatile List nonEmbeddableFields; + + protected boolean isEmbeddableField(ResolvedJavaField field) { + if (nonEmbeddableFields == null) { + synchronized (this) { + if (nonEmbeddableFields == null) { + List fields = new ArrayList<>(); + try { + fields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("TRUE"))); + fields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("FALSE"))); + + Class characterCacheClass = Character.class.getDeclaredClasses()[0]; + assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(characterCacheClass.getDeclaredField("cache"))); + + Class byteCacheClass = Byte.class.getDeclaredClasses()[0]; + assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(byteCacheClass.getDeclaredField("cache"))); + + Class shortCacheClass = Short.class.getDeclaredClasses()[0]; + assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(shortCacheClass.getDeclaredField("cache"))); + + Class integerCacheClass = Integer.class.getDeclaredClasses()[0]; + assert "java.lang.Integer$IntegerCache".equals(integerCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(integerCacheClass.getDeclaredField("cache"))); + + Class longCacheClass = Long.class.getDeclaredClasses()[0]; + assert "java.lang.Long$LongCache".equals(longCacheClass.getName()); + fields.add(metaAccess.lookupJavaField(longCacheClass.getDeclaredField("cache"))); + + fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("UNASSIGNED_STACK"))); + fields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL"))); + } catch (SecurityException | NoSuchFieldException e) { + throw new GraalError(e); + } + nonEmbeddableFields = fields; + } + } + } + return !nonEmbeddableFields.contains(field); } @Override @@ -112,18 +135,10 @@ public class HotSpotGraalConstantFieldProvider extends HotSpotConstantFieldProvi private final MetaAccessProvider metaAccess; - private ResolvedJavaType cachedStableOptionValueType; private ResolvedJavaType cachedHotSpotVMConfigType; private ResolvedJavaType cachedSnippetCounterType; private ResolvedJavaType cachedNodeClassType; - private ResolvedJavaType getStableOptionValueType() { - if (cachedStableOptionValueType == null) { - cachedStableOptionValueType = metaAccess.lookupJavaType(StableOptionValue.class); - } - return cachedStableOptionValueType; - } - private ResolvedJavaType getHotSpotVMConfigType() { if (cachedHotSpotVMConfigType == null) { cachedHotSpotVMConfigType = metaAccess.lookupJavaType(GraalHotSpotVMConfig.class); @@ -144,102 +159,4 @@ public class HotSpotGraalConstantFieldProvider extends HotSpotConstantFieldProvi } return cachedNodeClassType; } - - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean enabled = false; - assert enabled = true; - return enabled; - } - - public static final ThreadLocal FieldReadEnabledInImmutableCode = assertionsEnabled() ? new ThreadLocal<>() : null; - - /** - * Compares two {@link StackTraceElement}s for equality, ignoring differences in - * {@linkplain StackTraceElement#getLineNumber() line number}. - */ - private static boolean equalsIgnoringLine(StackTraceElement left, StackTraceElement right) { - return left.getClassName().equals(right.getClassName()) && left.getMethodName().equals(right.getMethodName()) && left.getFileName().equals(right.getFileName()); - } - - /** - * Separate out the static initialization of {@linkplain #isEmbeddable(ResolvedJavaField) - * embeddable fields} to eliminate cycles between clinit and other locks that could lead to - * deadlock. Static code that doesn't call back into type or field machinery is probably ok but - * anything else should be made lazy. - */ - static class ImmutableCodeLazy { - - /** - * If the compiler is configured for AOT mode, {@link #readConstantField} should be only - * called for snippets or replacements. - */ - static boolean isCalledForSnippets(MetaAccessProvider metaAccess) { - assert ImmutableCode.getValue(); - ResolvedJavaMethod makeGraphMethod = null; - ResolvedJavaMethod initMethod = null; - try { - Class rjm = ResolvedJavaMethod.class; - makeGraphMethod = metaAccess.lookupJavaMethod(ReplacementsImpl.class.getDeclaredMethod("makeGraph", rjm, Object[].class, rjm)); - initMethod = metaAccess.lookupJavaMethod(SnippetTemplate.AbstractTemplates.class.getDeclaredMethod("template", Arguments.class)); - } catch (NoSuchMethodException | SecurityException e) { - throw new GraalError(e); - } - StackTraceElement makeGraphSTE = makeGraphMethod.asStackTraceElement(0); - StackTraceElement initSTE = initMethod.asStackTraceElement(0); - - StackTraceElement[] stackTrace = new Exception().getStackTrace(); - for (StackTraceElement element : stackTrace) { - // Ignoring line numbers should not weaken this check too much while at - // the same time making it more robust against source code changes - if (equalsIgnoringLine(makeGraphSTE, element) || equalsIgnoringLine(initSTE, element)) { - return true; - } - } - return false; - } - - /** - * Determine if it's ok to embed the value of {@code field}. - */ - static boolean isEmbeddable(ResolvedJavaField field) { - assert ImmutableCode.getValue(); - return !embeddableFields.contains(field); - } - - private static final List embeddableFields = new ArrayList<>(); - static { - try { - MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess(); - embeddableFields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("TRUE"))); - embeddableFields.add(metaAccess.lookupJavaField(Boolean.class.getDeclaredField("FALSE"))); - - Class characterCacheClass = Character.class.getDeclaredClasses()[0]; - assert "java.lang.Character$CharacterCache".equals(characterCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(characterCacheClass.getDeclaredField("cache"))); - - Class byteCacheClass = Byte.class.getDeclaredClasses()[0]; - assert "java.lang.Byte$ByteCache".equals(byteCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(byteCacheClass.getDeclaredField("cache"))); - - Class shortCacheClass = Short.class.getDeclaredClasses()[0]; - assert "java.lang.Short$ShortCache".equals(shortCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(shortCacheClass.getDeclaredField("cache"))); - - Class integerCacheClass = Integer.class.getDeclaredClasses()[0]; - assert "java.lang.Integer$IntegerCache".equals(integerCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(integerCacheClass.getDeclaredField("cache"))); - - Class longCacheClass = Long.class.getDeclaredClasses()[0]; - assert "java.lang.Long$LongCache".equals(longCacheClass.getName()); - embeddableFields.add(metaAccess.lookupJavaField(longCacheClass.getDeclaredField("cache"))); - - embeddableFields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("UNASSIGNED_STACK"))); - embeddableFields.add(metaAccess.lookupJavaField(Throwable.class.getDeclaredField("SUPPRESSED_SENTINEL"))); - } catch (SecurityException | NoSuchFieldException e) { - throw new GraalError(e); - } - } - } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index 3f50151d1a0..acd3135615a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -22,14 +22,13 @@ */ package org.graalvm.compiler.hotspot.meta; -import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier; +import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; +import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_THREAD_OBJECT_LOCATION; import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing; - -import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; -import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved; +import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; import java.lang.invoke.ConstantCallSite; import java.lang.invoke.MutableCallSite; @@ -41,10 +40,8 @@ import java.util.zip.CRC32; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BytecodeProvider; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.FingerprintUtil; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.CurrentJavaThreadNode; import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions; @@ -53,8 +50,8 @@ import org.graalvm.compiler.hotspot.replacements.CRC32Substitutions; import org.graalvm.compiler.hotspot.replacements.CallSiteTargetNode; import org.graalvm.compiler.hotspot.replacements.CipherBlockChainingSubstitutions; import org.graalvm.compiler.hotspot.replacements.ClassGetHubNode; -import org.graalvm.compiler.hotspot.replacements.IdentityHashCodeNode; import org.graalvm.compiler.hotspot.replacements.HotSpotClassSubstitutions; +import org.graalvm.compiler.hotspot.replacements.IdentityHashCodeNode; import org.graalvm.compiler.hotspot.replacements.ObjectCloneNode; import org.graalvm.compiler.hotspot.replacements.ObjectSubstitutions; import org.graalvm.compiler.hotspot.replacements.ReflectionGetCallerClassNode; @@ -90,16 +87,18 @@ import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.util.GraphUtil; -import org.graalvm.compiler.options.StableOptionValue; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.replacements.InlineDuringParsingPlugin; -import org.graalvm.compiler.replacements.InlineGraalDirectivesPlugin; import org.graalvm.compiler.replacements.MethodHandlePlugin; import org.graalvm.compiler.replacements.NodeIntrinsificationProvider; import org.graalvm.compiler.replacements.ReplacementsImpl; import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins; -import org.graalvm.compiler.replacements.WordOperationPlugin; import org.graalvm.compiler.serviceprovider.GraalServices; +import org.graalvm.compiler.serviceprovider.JDK9Method; +import org.graalvm.compiler.word.WordOperationPlugin; import org.graalvm.compiler.word.WordTypes; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.hotspot.HotSpotObjectConstant; @@ -126,9 +125,10 @@ public class HotSpotGraphBuilderPlugins { * @param foreignCalls * @param stampProvider */ - public static Plugins create(GraalHotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, - SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider, ReplacementsImpl replacements) { - InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config); + public static Plugins create(CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, HotSpotWordTypes wordTypes, MetaAccessProvider metaAccess, + ConstantReflectionProvider constantReflection, SnippetReflectionProvider snippetReflection, ForeignCallsProvider foreignCalls, StampProvider stampProvider, + ReplacementsImpl replacements) { + InvocationPlugins invocationPlugins = new HotSpotInvocationPlugins(config, compilerConfiguration); Plugins plugins = new Plugins(invocationPlugins); NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes); @@ -137,7 +137,8 @@ public class HotSpotGraphBuilderPlugins { plugins.appendTypePlugin(nodePlugin); plugins.appendNodePlugin(nodePlugin); - if (GeneratePIC.getValue()) { + OptionValues options = replacements.getOptions(); + if (GeneratePIC.getValue(options)) { // AOT needs to filter out bad invokes plugins.prependNodePlugin(new NodePlugin() { @Override @@ -146,7 +147,7 @@ public class HotSpotGraphBuilderPlugins { return false; } // check if the holder has a valid fingerprint - if (FingerprintUtil.getFingerprint((HotSpotResolvedObjectType) method.getDeclaringClass()) == 0) { + if (((HotSpotResolvedObjectType) method.getDeclaringClass()).getFingerprint() == 0) { // Deopt otherwise b.append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); return true; @@ -161,7 +162,7 @@ public class HotSpotGraphBuilderPlugins { if (clazz.equals(String.class)) { return false; } - if (Class.class.isAssignableFrom(clazz) && FingerprintUtil.getFingerprint((HotSpotResolvedObjectType) type) != 0) { + if (Class.class.isAssignableFrom(clazz) && ((HotSpotResolvedObjectType) type).getFingerprint() != 0) { return false; } b.append(new DeoptimizeNode(InvalidateRecompile, Unresolved)); @@ -174,14 +175,13 @@ public class HotSpotGraphBuilderPlugins { } plugins.appendNodePlugin(new MethodHandlePlugin(constantReflection.getMethodHandleAccess(), true)); plugins.appendInlineInvokePlugin(replacements); - if (InlineDuringParsing.getValue()) { + if (InlineDuringParsing.getValue(options)) { plugins.appendInlineInvokePlugin(new InlineDuringParsingPlugin()); } - plugins.appendInlineInvokePlugin(new InlineGraalDirectivesPlugin()); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(options)) { plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin()); - if (TieredAOT.getValue()) { + if (TieredAOT.getValue(options)) { plugins.setProfilingPlugin(new HotSpotAOTProfilingPlugin()); } } @@ -190,15 +190,14 @@ public class HotSpotGraphBuilderPlugins { @Override public void run() { - BytecodeProvider replacementBytecodeProvider = replacements.getReplacementBytecodeProvider(); - registerObjectPlugins(invocationPlugins, replacementBytecodeProvider); + BytecodeProvider replacementBytecodeProvider = replacements.getDefaultReplacementBytecodeProvider(); + registerObjectPlugins(invocationPlugins, options, replacementBytecodeProvider); registerClassPlugins(plugins, config, replacementBytecodeProvider); registerSystemPlugins(invocationPlugins, foreignCalls); registerThreadPlugins(invocationPlugins, metaAccess, wordTypes, config, replacementBytecodeProvider); registerCallSitePlugins(invocationPlugins); registerReflectionPlugins(invocationPlugins, replacementBytecodeProvider); registerConstantPoolPlugins(invocationPlugins, wordTypes, config, replacementBytecodeProvider); - registerStableOptionPlugins(invocationPlugins, snippetReflection); registerAESPlugins(invocationPlugins, config, replacementBytecodeProvider); registerCRC32Plugins(invocationPlugins, config, replacementBytecodeProvider); registerBigIntegerPlugins(invocationPlugins, config, replacementBytecodeProvider); @@ -213,9 +212,9 @@ public class HotSpotGraphBuilderPlugins { return plugins; } - private static void registerObjectPlugins(InvocationPlugins plugins, BytecodeProvider bytecodeProvider) { + private static void registerObjectPlugins(InvocationPlugins plugins, OptionValues options, BytecodeProvider bytecodeProvider) { Registration r = new Registration(plugins, Object.class, bytecodeProvider); - if (!GeneratePIC.getValue()) { + if (!GeneratePIC.getValue(options)) { // FIXME: clone() requires speculation and requires a fix in here (to check that // b.getAssumptions() != null), and in ReplacementImpl.getSubstitution() where there is // an instantiation of IntrinsicGraphBuilder using a constructor that sets @@ -256,7 +255,7 @@ public class HotSpotGraphBuilderPlugins { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode object) { ValueNode javaClass = receiver.get(); - LogicNode condition = b.recursiveAppend(InstanceOfDynamicNode.create(b.getAssumptions(), b.getConstantReflection(), javaClass, object, true)); + LogicNode condition = b.append(InstanceOfDynamicNode.create(b.getAssumptions(), b.getConstantReflection(), javaClass, object, true)); if (condition.isTautology()) { b.addPush(JavaKind.Object, object); } else { @@ -327,7 +326,8 @@ public class HotSpotGraphBuilderPlugins { */ private static ValueNode getMetaspaceConstantPool(GraphBuilderContext b, ValueNode constantPoolOop, WordTypes wordTypes, GraalHotSpotVMConfig config) { // ConstantPool.constantPoolOop is in fact the holder class. - ClassGetHubNode klass = b.add(new ClassGetHubNode(constantPoolOop)); + ValueNode value = b.nullCheckedValue(constantPoolOop, DeoptimizationAction.None); + ValueNode klass = b.add(ClassGetHubNode.create(value, b.getMetaAccess(), b.getConstantReflection(), false)); boolean notCompressible = false; AddressNode constantsAddress = b.add(new OffsetAddressNode(klass, b.add(ConstantNode.forLong(config.instanceKlassConstantsOffset)))); @@ -442,21 +442,6 @@ public class HotSpotGraphBuilderPlugins { r.registerMethodSubstitution(ThreadSubstitutions.class, "isInterrupted", Receiver.class, boolean.class); } - private static void registerStableOptionPlugins(InvocationPlugins plugins, SnippetReflectionProvider snippetReflection) { - Registration r = new Registration(plugins, StableOptionValue.class); - r.register1("getValue", Receiver.class, new InvocationPlugin() { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - if (receiver.isConstant()) { - StableOptionValue option = snippetReflection.asObject(StableOptionValue.class, (JavaConstant) receiver.get().asConstant()); - b.addPush(JavaKind.Object, ConstantNode.forConstant(snippetReflection.forObject(option.getValue()), b.getMetaAccess())); - return true; - } - return false; - } - }); - } - public static final String cbcEncryptName; public static final String cbcDecryptName; public static final String aesEncryptName; @@ -466,7 +451,7 @@ public class HotSpotGraphBuilderPlugins { public static final String constantPoolClass; static { - if (Java8OrEarlier) { + if (JDK9Method.Java8OrEarlier) { cbcEncryptName = "encrypt"; cbcDecryptName = "decrypt"; aesEncryptName = "encryptBlock"; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index 726087805f3..ff2fb37b411 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -22,15 +22,11 @@ */ package org.graalvm.compiler.hotspot.meta; +import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_DREM; import static org.graalvm.compiler.core.target.Backend.ARITHMETIC_FREM; -import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.BACKEDGE_EVENT; -import static org.graalvm.compiler.hotspot.HotSpotBackend.INVOCATION_EVENT; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; -import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK_WITH_ORIGINAL_KEY; @@ -38,8 +34,9 @@ import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_WITH_ORIGINAL_ import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT; import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT_BLOCK; import static org.graalvm.compiler.hotspot.HotSpotBackend.EXCEPTION_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.FETCH_UNROLL_INFO; import static org.graalvm.compiler.hotspot.HotSpotBackend.IC_MISS_HANDLER; +import static org.graalvm.compiler.hotspot.HotSpotBackend.INITIALIZE_KLASS_BY_SYMBOL; +import static org.graalvm.compiler.hotspot.HotSpotBackend.INVOCATION_EVENT; import static org.graalvm.compiler.hotspot.HotSpotBackend.MONTGOMERY_MULTIPLY; import static org.graalvm.compiler.hotspot.HotSpotBackend.MONTGOMERY_SQUARE; import static org.graalvm.compiler.hotspot.HotSpotBackend.MULTIPLY_TO_LEN; @@ -47,16 +44,16 @@ import static org.graalvm.compiler.hotspot.HotSpotBackend.MUL_ADD; import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_ARRAY; import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_INSTANCE; import static org.graalvm.compiler.hotspot.HotSpotBackend.NEW_MULTI_ARRAY; +import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_KLASS_BY_SYMBOL; +import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS; +import static org.graalvm.compiler.hotspot.HotSpotBackend.RESOLVE_STRING_BY_SYMBOL; import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA2_IMPL_COMPRESS; import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA5_IMPL_COMPRESS; import static org.graalvm.compiler.hotspot.HotSpotBackend.SHA_IMPL_COMPRESS; import static org.graalvm.compiler.hotspot.HotSpotBackend.SQUARE_TO_LEN; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNCOMMON_TRAP; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNPACK_FRAMES; import static org.graalvm.compiler.hotspot.HotSpotBackend.UNWIND_EXCEPTION_TO_CALLER; import static org.graalvm.compiler.hotspot.HotSpotBackend.VM_ERROR; import static org.graalvm.compiler.hotspot.HotSpotBackend.WRONG_METHOD_HANDLER; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF; @@ -77,7 +74,6 @@ import static org.graalvm.compiler.hotspot.replacements.MonitorSnippets.MONITORE import static org.graalvm.compiler.hotspot.replacements.MonitorSnippets.MONITOREXIT; import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.DYNAMIC_NEW_ARRAY; import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.DYNAMIC_NEW_INSTANCE; -import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.INIT_LOCATION; import static org.graalvm.compiler.hotspot.replacements.ThreadSubstitutions.THREAD_IS_INTERRUPTED; import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.G1WBPOSTCALL; import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.G1WBPRECALL; @@ -99,20 +95,16 @@ import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.Una import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10; import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN; import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN; -import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import java.util.EnumMap; -import java.util.HashMap; -import java.util.Map; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.hotspot.CompilerRuntimeHotSpotVMConfig; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; -import org.graalvm.compiler.hotspot.CompilerRuntimeHotSpotVMConfig; import org.graalvm.compiler.hotspot.stubs.ArrayStoreExceptionStub; import org.graalvm.compiler.hotspot.stubs.ClassCastExceptionStub; import org.graalvm.compiler.hotspot.stubs.CreateExceptionStub; @@ -125,8 +117,11 @@ import org.graalvm.compiler.hotspot.stubs.Stub; import org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub; import org.graalvm.compiler.hotspot.stubs.VerifyOopStub; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordTypes; +import org.graalvm.util.EconomicMap; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -183,7 +178,7 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall } } - private void registerArraycopyDescriptor(Map descMap, JavaKind kind, boolean aligned, boolean disjoint, boolean uninit, boolean killAny, long routine) { + private void registerArraycopyDescriptor(EconomicMap descMap, JavaKind kind, boolean aligned, boolean disjoint, boolean uninit, boolean killAny, long routine) { ForeignCallDescriptor desc = descMap.get(routine); if (desc == null) { desc = buildDescriptor(kind, aligned, disjoint, uninit, killAny, routine); @@ -231,7 +226,7 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall * but only within the same Kind. For instance short and char are the same copy routines but * they kill different memory so they still have to be distinct. */ - Map descMap = new HashMap<>(); + EconomicMap descMap = EconomicMap.create(); registerArraycopyDescriptor(descMap, kind, false, false, uninit, false, routine); registerArraycopyDescriptor(descMap, kind, true, false, uninit, false, alignedRoutine); registerArraycopyDescriptor(descMap, kind, false, true, uninit, false, disjointRoutine); @@ -245,12 +240,10 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall } } - public void initialize(HotSpotProviders providers) { + public void initialize(HotSpotProviders providers, OptionValues options) { GraalHotSpotVMConfig c = runtime.getVMConfig(); - if (!PreferGraalStubs.getValue()) { - registerForeignCall(DEOPTIMIZATION_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - registerForeignCall(UNCOMMON_TRAP_HANDLER, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - } + registerForeignCall(DEOPTIMIZATION_HANDLER, c.handleDeoptStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + registerForeignCall(UNCOMMON_TRAP_HANDLER, c.uncommonTrapStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(IC_MISS_HANDLER, c.inlineCacheMissStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(JAVA_TIME_MILLIS, c.javaTimeMillisAddress, NativeCall, DESTROYS_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); @@ -269,17 +262,8 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); - registerForeignCall(FETCH_UNROLL_INFO, c.deoptimizationFetchUnrollInfo, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any()); - registerForeignCall(UNCOMMON_TRAP, c.deoptimizationUncommonTrap, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, NOT_REEXECUTABLE, any()); - - /* - * We cannot use LEAF_SP here because on some architectures we have to align the stack - * manually before calling into the VM. See {@link - * AMD64HotSpotEnterUnpackFramesStackFrameOp#emitCode}. - */ - registerForeignCall(UNPACK_FRAMES, c.deoptimizationUnpackFrames, NativeCall, DESTROYS_REGISTERS, LEAF, NOT_REEXECUTABLE, any()); CreateExceptionStub.registerForeignCalls(c, this); @@ -290,47 +274,47 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); registerForeignCall(ASSERTION_VM_MESSAGE_C, c.vmMessageAddress, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS); - link(new NewInstanceStub(providers, registerStubCall(NEW_INSTANCE, REEXECUTABLE, SAFEPOINT, INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION))); - link(new NewArrayStub(providers, registerStubCall(NEW_ARRAY, REEXECUTABLE, SAFEPOINT, INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION))); - link(new ExceptionHandlerStub(providers, foreignCalls.get(EXCEPTION_HANDLER))); - link(new UnwindExceptionToCallerStub(providers, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, SAFEPOINT, any()))); - link(new VerifyOopStub(providers, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF_NOFP, NO_LOCATIONS))); - link(new ArrayStoreExceptionStub(providers, registerStubCall(CREATE_ARRAY_STORE_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - link(new ClassCastExceptionStub(providers, registerStubCall(CREATE_CLASS_CAST_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - link(new NullPointerExceptionStub(providers, registerStubCall(CREATE_NULL_POINTER_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - link(new OutOfBoundsExceptionStub(providers, registerStubCall(CREATE_OUT_OF_BOUNDS_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); + link(new NewInstanceStub(options, providers, registerStubCall(NEW_INSTANCE, REEXECUTABLE, SAFEPOINT, TLAB_TOP_LOCATION, TLAB_END_LOCATION))); + link(new NewArrayStub(options, providers, registerStubCall(NEW_ARRAY, REEXECUTABLE, SAFEPOINT, TLAB_TOP_LOCATION, TLAB_END_LOCATION))); + link(new ExceptionHandlerStub(options, providers, foreignCalls.get(EXCEPTION_HANDLER))); + link(new UnwindExceptionToCallerStub(options, providers, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, NOT_REEXECUTABLE, SAFEPOINT, any()))); + link(new VerifyOopStub(options, providers, registerStubCall(VERIFY_OOP, REEXECUTABLE, LEAF_NOFP, NO_LOCATIONS))); + link(new ArrayStoreExceptionStub(options, providers, registerStubCall(CREATE_ARRAY_STORE_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); + link(new ClassCastExceptionStub(options, providers, registerStubCall(CREATE_CLASS_CAST_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); + link(new NullPointerExceptionStub(options, providers, registerStubCall(CREATE_NULL_POINTER_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); + link(new OutOfBoundsExceptionStub(options, providers, registerStubCall(CREATE_OUT_OF_BOUNDS_EXCEPTION, REEXECUTABLE, SAFEPOINT, any()))); - linkForeignCall(providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, MARK_WORD_LOCATION); - linkForeignCall(providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); - linkForeignCall(providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); - linkForeignCall(providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, STACK_INSPECTABLE_LEAF, NOT_REEXECUTABLE, any()); - linkForeignCall(providers, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - linkForeignCall(providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, INIT_LOCATION); - linkForeignCall(providers, DYNAMIC_NEW_INSTANCE, c.dynamicNewInstanceAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, INIT_LOCATION); - linkForeignCall(providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NOFP, NOT_REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, IDENTITY_HASHCODE, c.identityHashCodeAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, MARK_WORD_LOCATION); + linkForeignCall(options, providers, REGISTER_FINALIZER, c.registerFinalizerAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); + linkForeignCall(options, providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); + linkForeignCall(options, providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, STACK_INSPECTABLE_LEAF, NOT_REEXECUTABLE, any()); + linkForeignCall(options, providers, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + linkForeignCall(options, providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE); + linkForeignCall(options, providers, DYNAMIC_NEW_INSTANCE, c.dynamicNewInstanceAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE); + linkForeignCall(options, providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, LOG_OBJECT, c.logObjectAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, LOG_PRIMITIVE, c.logPrimitiveAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, VM_ERROR, c.vmErrorAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, OSR_MIGRATION_END, c.osrMigrationEndAddress, DONT_PREPEND_THREAD, LEAF_NOFP, NOT_REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, G1WBPRECALL, c.writeBarrierPreAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, G1WBPOSTCALL, c.writeBarrierPostAddress, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, VALIDATE_OBJECT, c.validateObject, PREPEND_THREAD, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(options)) { registerForeignCall(WRONG_METHOD_HANDLER, c.handleWrongMethodStub, NativeCall, PRESERVES_REGISTERS, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS); CompilerRuntimeHotSpotVMConfig cr = new CompilerRuntimeHotSpotVMConfig(HotSpotJVMCIRuntime.runtime().getConfigStore()); - linkForeignCall(providers, RESOLVE_STRING_BY_SYMBOL, cr.resolveStringBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - linkForeignCall(providers, RESOLVE_KLASS_BY_SYMBOL, cr.resolveKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); - linkForeignCall(providers, RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS, cr.resolveMethodBySymbolAndLoadCounters, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, INITIALIZE_KLASS_BY_SYMBOL, cr.initializeKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); - linkForeignCall(providers, INVOCATION_EVENT, cr.invocationEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); - linkForeignCall(providers, BACKEDGE_EVENT, cr.backedgeEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, RESOLVE_STRING_BY_SYMBOL, cr.resolveStringBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + linkForeignCall(options, providers, RESOLVE_KLASS_BY_SYMBOL, cr.resolveKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); + linkForeignCall(options, providers, RESOLVE_METHOD_BY_SYMBOL_AND_LOAD_COUNTERS, cr.resolveMethodBySymbolAndLoadCounters, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, INITIALIZE_KLASS_BY_SYMBOL, cr.initializeKlassBySymbol, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); + linkForeignCall(options, providers, INVOCATION_EVENT, cr.invocationEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); + linkForeignCall(options, providers, BACKEDGE_EVENT, cr.backedgeEvent, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS); } // Cannot be a leaf as VM acquires Thread_lock which requires thread_in_vm state - linkForeignCall(providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); + linkForeignCall(options, providers, THREAD_IS_INTERRUPTED, c.threadIsInterruptedAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any()); - linkForeignCall(providers, TEST_DEOPTIMIZE_CALL_INT, c.testDeoptimizeCallInt, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); + linkForeignCall(options, providers, TEST_DEOPTIMIZE_CALL_INT, c.testDeoptimizeCallInt, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, any()); registerArrayCopy(JavaKind.Byte, c.jbyteArraycopy, c.jbyteAlignedArraycopy, c.jbyteDisjointArraycopy, c.jbyteAlignedDisjointArraycopy); registerArrayCopy(JavaKind.Boolean, c.jbyteArraycopy, c.jbyteAlignedArraycopy, c.jbyteDisjointArraycopy, c.jbyteAlignedDisjointArraycopy); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java index 244579972dd..076d4a98700 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java @@ -22,9 +22,13 @@ */ package org.graalvm.compiler.hotspot.meta; +import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; + import java.lang.reflect.Type; +import java.util.Set; import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -35,8 +39,12 @@ import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.type.StampTool; +import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.replacements.nodes.MacroNode; +import org.graalvm.compiler.serviceprovider.JDK9Method; +import org.graalvm.util.EconomicSet; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaType; @@ -44,10 +52,19 @@ import jdk.vm.ci.meta.ResolvedJavaType; * Extension of {@link InvocationPlugins} that disables plugins based on runtime configuration. */ final class HotSpotInvocationPlugins extends InvocationPlugins { - final GraalHotSpotVMConfig config; + private final GraalHotSpotVMConfig config; + private final EconomicSet trustedModules; + private final ClassLoader extLoader; - HotSpotInvocationPlugins(GraalHotSpotVMConfig config) { + HotSpotInvocationPlugins(GraalHotSpotVMConfig config, CompilerConfiguration compilerConfiguration) { this.config = config; + if (Java8OrEarlier) { + extLoader = getExtLoader(); + trustedModules = null; + } else { + extLoader = null; + trustedModules = initTrustedModules(compilerConfiguration); + } } @Override @@ -71,7 +88,7 @@ final class HotSpotInvocationPlugins extends InvocationPlugins { assert plugin.inlineOnly() : String.format("plugin that creates a %s (%s) must return true for inlineOnly(): %s", MacroNode.class.getSimpleName(), node, plugin); } } - if (GraalOptions.ImmutableCode.getValue()) { + if (GraalOptions.ImmutableCode.getValue(b.getOptions())) { for (Node node : newNodes) { if (node.hasUsages() && node instanceof ConstantNode) { ConstantNode c = (ConstantNode) node; @@ -95,4 +112,71 @@ final class HotSpotInvocationPlugins extends InvocationPlugins { ResolvedJavaType type = StampTool.typeOrNull(node); return type != null && "Ljava/lang/Class;".equals(type.getName()); } + + /** + * {@inheritDoc} + * + * On JDK 8, only classes loaded by the boot, JVMCI or extension class loaders are trusted. + * + * On JDK 9 and later, only classes in the {@link CompilerConfiguration} defining module or any + * of its module dependencies are trusted. + */ + @Override + protected boolean canBeIntrinsified(ResolvedJavaType declaringClass) { + if (declaringClass instanceof HotSpotResolvedJavaType) { + Class javaClass = ((HotSpotResolvedJavaType) declaringClass).mirror(); + if (Java8OrEarlier) { + ClassLoader cl = javaClass.getClassLoader(); + return cl == null || cl == getClass().getClassLoader() || cl == extLoader; + } else { + Object module = JDK9Method.getModule.invoke(javaClass); + return trustedModules.contains(module); + } + } + return false; + } + + private static ClassLoader getExtLoader() { + try { + Object launcher = Class.forName("sun.misc.Launcher").getMethod("getLauncher").invoke(null); + ClassLoader appLoader = (ClassLoader) launcher.getClass().getMethod("getClassLoader").invoke(launcher); + ClassLoader extLoader = appLoader.getParent(); + assert extLoader.getClass().getName().equals("sun.misc.Launcher$ExtClassLoader") : extLoader; + return extLoader; + } catch (Exception e) { + throw new GraalError(e); + } + } + + private static EconomicSet initTrustedModules(CompilerConfiguration compilerConfiguration) throws GraalError { + try { + EconomicSet res = EconomicSet.create(); + Object compilerConfigurationModule = JDK9Method.getModule.invoke(compilerConfiguration.getClass()); + res.add(compilerConfigurationModule); + Class moduleClass = compilerConfigurationModule.getClass(); + Object layer = new JDK9Method(moduleClass, "getLayer").invoke(compilerConfigurationModule); + Class layerClass = layer.getClass(); + JDK9Method getName = new JDK9Method(moduleClass, "getName"); + Set modules = new JDK9Method(layerClass, "modules").invoke(layer); + Object descriptor = new JDK9Method(moduleClass, "getDescriptor").invoke(compilerConfigurationModule); + Class moduleDescriptorClass = descriptor.getClass(); + Set requires = new JDK9Method(moduleDescriptorClass, "requires").invoke(descriptor); + JDK9Method requireNameGetter = null; + for (Object require : requires) { + if (requireNameGetter == null) { + requireNameGetter = new JDK9Method(require.getClass(), "name"); + } + String name = requireNameGetter.invoke(require); + for (Object module : modules) { + String moduleName = getName.invoke(module); + if (moduleName.equals(name)) { + res.add(module); + } + } + } + return res; + } catch (Exception e) { + throw new GraalError(e); + } + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java index 95b21a0d201..64c85ac3b71 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotLoweringProvider.java @@ -22,13 +22,15 @@ */ package org.graalvm.compiler.hotspot.meta; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.nodes.spi.LoweringProvider; +import org.graalvm.compiler.options.OptionValues; /** * HotSpot implementation of {@link LoweringProvider}. */ public interface HotSpotLoweringProvider extends LoweringProvider { - void initialize(HotSpotProviders providers, GraalHotSpotVMConfig config); + void initialize(OptionValues options, Iterable factories, HotSpotProviders providers, GraalHotSpotVMConfig config); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java index 10b2255a3dc..c0f91779bfb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java @@ -23,7 +23,6 @@ package org.graalvm.compiler.hotspot.meta; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; -import static org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider.FieldReadEnabledInImmutableCode; import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.nodes.ConstantNode; @@ -34,8 +33,8 @@ import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.NodePlugin; import org.graalvm.compiler.nodes.graphbuilderconf.TypePlugin; import org.graalvm.compiler.nodes.util.ConstantFoldUtil; -import org.graalvm.compiler.replacements.WordOperationPlugin; import org.graalvm.compiler.word.Word; +import org.graalvm.compiler.word.WordOperationPlugin; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; @@ -90,7 +89,7 @@ public final class HotSpotNodePlugin implements NodePlugin, TypePlugin { @Override public boolean handleLoadField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field) { - if (!ImmutableCode.getValue() || b.parsingIntrinsic()) { + if (!ImmutableCode.getValue(b.getOptions()) || b.parsingIntrinsic()) { if (object.isConstant()) { JavaConstant asJavaConstant = object.asJavaConstant(); if (tryReadField(b, field, asJavaConstant)) { @@ -106,7 +105,7 @@ public final class HotSpotNodePlugin implements NodePlugin, TypePlugin { @Override public boolean handleLoadStaticField(GraphBuilderContext b, ResolvedJavaField field) { - if (!ImmutableCode.getValue() || b.parsingIntrinsic()) { + if (!ImmutableCode.getValue(b.getOptions()) || b.parsingIntrinsic()) { if (tryReadField(b, field, null)) { return true; } @@ -118,21 +117,11 @@ public final class HotSpotNodePlugin implements NodePlugin, TypePlugin { } private static boolean tryReadField(GraphBuilderContext b, ResolvedJavaField field, JavaConstant object) { - // FieldReadEnabledInImmutableCode is non null only if assertions are enabled - if (FieldReadEnabledInImmutableCode != null && ImmutableCode.getValue()) { - FieldReadEnabledInImmutableCode.set(Boolean.TRUE); - try { - return tryConstantFold(b, field, object); - } finally { - FieldReadEnabledInImmutableCode.set(null); - } - } else { - return tryConstantFold(b, field, object); - } + return tryConstantFold(b, field, object); } private static boolean tryConstantFold(GraphBuilderContext b, ResolvedJavaField field, JavaConstant object) { - ConstantNode result = ConstantFoldUtil.tryConstantFold(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(), field, object); + ConstantNode result = ConstantFoldUtil.tryConstantFold(b.getConstantFieldProvider(), b.getConstantReflection(), b.getMetaAccess(), field, object, b.getOptions()); if (result != null) { result = b.getGraph().unique(result); b.push(field.getJavaKind(), result); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java index d0dad67e740..311e4199e97 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProfilingPlugin.java @@ -33,28 +33,29 @@ import org.graalvm.compiler.nodes.calc.ConditionalNode; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.ProfilingPlugin; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.meta.ResolvedJavaMethod; public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { public static class Options { @Option(help = "Emit profiling of invokes", type = OptionType.Expert)// - public static final OptionValue ProfileInvokes = new OptionValue<>(true); + public static final OptionKey ProfileInvokes = new OptionKey<>(true); @Option(help = "Emit profiling of backedges", type = OptionType.Expert)// - public static final OptionValue ProfileBackedges = new OptionValue<>(true); + public static final OptionKey ProfileBackedges = new OptionKey<>(true); } - public abstract int invokeNotifyFreqLog(); + public abstract int invokeNotifyFreqLog(OptionValues options); - public abstract int invokeInlineeNotifyFreqLog(); + public abstract int invokeInlineeNotifyFreqLog(OptionValues options); - public abstract int invokeProfilePobabilityLog(); + public abstract int invokeProfilePobabilityLog(OptionValues options); - public abstract int backedgeNotifyFreqLog(); + public abstract int backedgeNotifyFreqLog(OptionValues options); - public abstract int backedgeProfilePobabilityLog(); + public abstract int backedgeProfilePobabilityLog(OptionValues options); @Override public boolean shouldProfile(GraphBuilderContext builder, ResolvedJavaMethod method) { @@ -64,8 +65,9 @@ public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { @Override public void profileInvoke(GraphBuilderContext builder, ResolvedJavaMethod method, FrameState frameState) { assert shouldProfile(builder, method); - if (Options.ProfileInvokes.getValue() && !method.isClassInitializer()) { - ProfileNode p = builder.append(new ProfileInvokeNode(method, invokeNotifyFreqLog(), invokeProfilePobabilityLog())); + OptionValues options = builder.getOptions(); + if (Options.ProfileInvokes.getValue(options) && !method.isClassInitializer()) { + ProfileNode p = builder.append(new ProfileInvokeNode(method, invokeNotifyFreqLog(options), invokeProfilePobabilityLog(options))); p.setStateBefore(frameState); } } @@ -73,8 +75,9 @@ public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { @Override public void profileGoto(GraphBuilderContext builder, ResolvedJavaMethod method, int bci, int targetBci, FrameState frameState) { assert shouldProfile(builder, method); - if (Options.ProfileBackedges.getValue() && targetBci <= bci) { - ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(), backedgeProfilePobabilityLog(), bci, targetBci)); + OptionValues options = builder.getOptions(); + if (Options.ProfileBackedges.getValue(options) && targetBci <= bci) { + ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(options), backedgeProfilePobabilityLog(options), bci, targetBci)); p.setStateBefore(frameState); } } @@ -82,7 +85,8 @@ public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { @Override public void profileIf(GraphBuilderContext builder, ResolvedJavaMethod method, int bci, LogicNode condition, int trueBranchBci, int falseBranchBci, FrameState frameState) { assert shouldProfile(builder, method); - if (Options.ProfileBackedges.getValue() && (falseBranchBci <= bci || trueBranchBci <= bci)) { + OptionValues options = builder.getOptions(); + if (Options.ProfileBackedges.getValue(options) && (falseBranchBci <= bci || trueBranchBci <= bci)) { boolean negate = false; int targetBci = trueBranchBci; if (falseBranchBci <= bci) { @@ -95,7 +99,7 @@ public abstract class HotSpotProfilingPlugin implements ProfilingPlugin { ValueNode trueValue = builder.append(ConstantNode.forBoolean(!negate)); ValueNode falseValue = builder.append(ConstantNode.forBoolean(negate)); ConditionalNode branchCondition = builder.append(new ConditionalNode(condition, trueValue, falseValue)); - ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(), backedgeProfilePobabilityLog(), branchCondition, bci, targetBci)); + ProfileNode p = builder.append(new ProfileBranchNode(method, backedgeNotifyFreqLog(options), backedgeProfilePobabilityLog(options), branchCondition, bci, targetBci)); p.setStateBefore(frameState); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java index 2b65a88709b..6935b9b695e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotProviders.java @@ -27,7 +27,6 @@ import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.spi.LoweringProvider; -import org.graalvm.compiler.nodes.spi.NodeCostProvider; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.phases.tiers.SuitesProvider; import org.graalvm.compiler.phases.util.Providers; @@ -49,10 +48,10 @@ public class HotSpotProviders extends Providers { private final Plugins graphBuilderPlugins; public HotSpotProviders(MetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantField, - HotSpotForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, NodeCostProvider nodeCostProvider, SuitesProvider suites, + HotSpotForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, SuitesProvider suites, HotSpotRegistersProvider registers, SnippetReflectionProvider snippetReflection, HotSpotWordTypes wordTypes, Plugins graphBuilderPlugins) { - super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, new HotSpotStampProvider(), nodeCostProvider); + super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, new HotSpotStampProvider()); this.suites = suites; this.registers = registers; this.snippetReflection = snippetReflection; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java index 32d7281b31a..4649b5ed15f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java @@ -22,17 +22,16 @@ */ package org.graalvm.compiler.hotspot.meta; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.core.common.GraalOptions.VerifyPhases; import java.util.ListIterator; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider; import org.graalvm.compiler.hotspot.HotSpotInstructionProfiling; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.phases.AheadOfTimeVerificationPhase; import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase; import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; @@ -50,16 +49,14 @@ import org.graalvm.compiler.nodes.SimplifyingGraphDecoder; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.PhaseSuite; -import org.graalvm.compiler.phases.common.AddressLoweringPhase; -import org.graalvm.compiler.phases.common.AddressLoweringPhase.AddressLowering; import org.graalvm.compiler.phases.common.CanonicalizerPhase; -import org.graalvm.compiler.phases.common.ExpandLogicPhase; -import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase; import org.graalvm.compiler.phases.common.LoweringPhase; import org.graalvm.compiler.phases.common.inlining.InliningPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.graalvm.compiler.phases.tiers.MidTierContext; import org.graalvm.compiler.phases.tiers.Suites; import org.graalvm.compiler.phases.tiers.SuitesCreator; @@ -71,36 +68,34 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { protected final GraalHotSpotVMConfig config; protected final HotSpotGraalRuntimeProvider runtime; - private final AddressLowering addressLowering; private final SuitesCreator defaultSuitesCreator; - public HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, AddressLowering addressLowering) { + public HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime) { this.defaultSuitesCreator = defaultSuitesCreator; this.config = config; this.runtime = runtime; - this.addressLowering = addressLowering; this.defaultGraphBuilderSuite = createGraphBuilderSuite(); } @Override - public Suites createSuites() { - Suites ret = defaultSuitesCreator.createSuites(); + public Suites createSuites(OptionValues options) { + Suites ret = defaultSuitesCreator.createSuites(options); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(options)) { // lowering introduces class constants, therefore it must be after lowering - ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config.classMirrorOffset, config.useCompressedOops ? config.getOopEncoding() : null)); - if (VerifyPhases.getValue()) { + ret.getHighTier().appendPhase(new LoadJavaMirrorWithKlassPhase(config)); + if (VerifyPhases.getValue(options)) { ret.getHighTier().appendPhase(new AheadOfTimeVerificationPhase()); } - if (GeneratePIC.getValue()) { - // EliminateRedundantInitializationPhase must happen before the first lowering. + if (GeneratePIC.getValue(options)) { ListIterator> highTierLowering = ret.getHighTier().findPhase(LoweringPhase.class); highTierLowering.previous(); highTierLowering.add(new EliminateRedundantInitializationPhase()); - if (HotSpotAOTProfilingPlugin.Options.TieredAOT.getValue()) { - highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue())); + if (HotSpotAOTProfilingPlugin.Options.TieredAOT.getValue(options)) { + highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue(options))); } - ret.getMidTier().findPhase(LoopSafepointInsertionPhase.class).add(new ReplaceConstantNodesPhase()); + ListIterator> midTierLowering = ret.getMidTier().findPhase(LoweringPhase.class); + midTierLowering.add(new ReplaceConstantNodesPhase()); // Replace inlining policy ListIterator> iter = ret.getHighTier().findPhase(InliningPhase.class); @@ -111,12 +106,10 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { } ret.getMidTier().appendPhase(new WriteBarrierAdditionPhase(config)); - if (VerifyPhases.getValue()) { + if (VerifyPhases.getValue(options)) { ret.getMidTier().appendPhase(new WriteBarrierVerificationPhase(config)); } - ret.getLowTier().findPhase(ExpandLogicPhase.class).add(new AddressLoweringPhase(addressLowering)); - return ret; } @@ -131,7 +124,7 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { * encoding and decoding process work correctly. The decoding performs canonicalization during * decoding, so the decoded graph can be different than the encoded graph - we cannot check them * for equality here. However, the encoder {@link GraphEncoder#verifyEncoding verifies the - * encoding itself}, i.e., performs a decoding without canoncialization and checks the graphs + * encoding itself}, i.e., performs a decoding without canonicalization and checks the graphs * for equality. */ private boolean appendGraphEncoderTest(PhaseSuite suite) { @@ -140,10 +133,10 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { protected void run(StructuredGraph graph, HighTierContext context) { EncodedGraph encodedGraph = GraphEncoder.encodeSingleGraph(graph, runtime.getTarget().arch); - SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(context.getMetaAccess(), context.getConstantReflection(), context.getConstantFieldProvider(), - context.getStampProvider(), !ImmutableCode.getValue(), runtime.getTarget().arch); - StructuredGraph targetGraph = new StructuredGraph(graph.method(), AllowAssumptions.YES, INVALID_COMPILATION_ID); - graphDecoder.decode(targetGraph, encodedGraph); + StructuredGraph targetGraph = new StructuredGraph.Builder(graph.getOptions(), graph.getDebug(), AllowAssumptions.YES).method(graph.method()).build(); + SimplifyingGraphDecoder graphDecoder = new SimplifyingGraphDecoder(runtime.getTarget().arch, targetGraph, context.getMetaAccess(), context.getConstantReflection(), + context.getConstantFieldProvider(), context.getStampProvider(), !ImmutableCode.getValue(graph.getOptions())); + graphDecoder.decode(encodedGraph); } @Override @@ -169,9 +162,9 @@ public class HotSpotSuitesProvider extends SuitesProviderBase { } @Override - public LIRSuites createLIRSuites() { - LIRSuites suites = defaultSuitesCreator.createLIRSuites(); - String profileInstructions = HotSpotBackend.Options.ASMInstructionProfiling.getValue(); + public LIRSuites createLIRSuites(OptionValues options) { + LIRSuites suites = defaultSuitesCreator.createLIRSuites(options); + String profileInstructions = HotSpotBackend.Options.ASMInstructionProfiling.getValue(options); if (profileInstructions != null) { suites.getPostAllocationOptimizationStage().appendPhase(new HotSpotInstructionProfiling(profileInstructions)); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java index cb47a5ad446..354b8e1f8af 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java @@ -22,14 +22,13 @@ */ package org.graalvm.compiler.hotspot.meta; -import static org.graalvm.compiler.core.common.LocationIdentity.any; import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.POINTER_EQ; import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.POINTER_NE; import static org.graalvm.compiler.nodes.ConstantNode.forBoolean; +import static org.graalvm.word.LocationIdentity.any; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.bytecode.BridgeMethodUtils; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.debug.GraalError; @@ -40,7 +39,6 @@ import org.graalvm.compiler.hotspot.nodes.type.MethodPointerStamp; import org.graalvm.compiler.hotspot.word.HotSpotOperation; import org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode; import org.graalvm.compiler.hotspot.word.PointerCastNode; -import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.LogicNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ConditionalNode; @@ -52,8 +50,9 @@ import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.type.StampTool; -import org.graalvm.compiler.replacements.WordOperationPlugin; +import org.graalvm.compiler.word.WordOperationPlugin; import org.graalvm.compiler.word.WordTypes; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -110,7 +109,7 @@ class HotSpotWordOperationPlugin extends WordOperationPlugin { PointerEqualsNode comparison = b.add(new PointerEqualsNode(left, right)); ValueNode eqValue = b.add(forBoolean(opcode == POINTER_EQ)); ValueNode neValue = b.add(forBoolean(opcode == POINTER_NE)); - b.addPush(returnKind, new ConditionalNode(comparison, eqValue, neValue)); + b.addPush(returnKind, ConditionalNode.create(comparison, eqValue, neValue)); break; case IS_NULL: @@ -118,8 +117,8 @@ class HotSpotWordOperationPlugin extends WordOperationPlugin { ValueNode pointer = args[0]; assert pointer.stamp() instanceof MetaspacePointerStamp; - LogicNode isNull = b.add(IsNullNode.create(pointer)); - b.addPush(returnKind, new ConditionalNode(isNull, b.add(forBoolean(true)), b.add(forBoolean(false)))); + LogicNode isNull = b.addWithInputs(IsNullNode.create(pointer)); + b.addPush(returnKind, ConditionalNode.create(isNull, b.add(forBoolean(true)), b.add(forBoolean(false)))); break; case FROM_POINTER: @@ -149,11 +148,6 @@ class HotSpotWordOperationPlugin extends WordOperationPlugin { location = snippetReflection.asObject(LocationIdentity.class, args[2].asJavaConstant()); } ReadNode read = b.add(new ReadNode(address, location, readStamp, BarrierType.NONE)); - /* - * The read must not float outside its block otherwise it may float above an - * explicit zero check on its base address. - */ - read.setGuard(AbstractBeginNode.prevBegin(read)); b.push(returnKind, read); break; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java index d3c5b867643..63657a69d24 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java @@ -26,7 +26,6 @@ import static org.graalvm.compiler.nodeinfo.InputType.Memory; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; @@ -39,7 +38,9 @@ import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordTypes; +import org.graalvm.word.LocationIdentity; +import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.Value; /** @@ -59,6 +60,11 @@ public final class BeginLockScopeNode extends AbstractMemoryCheckpoint implement this.lockDepth = lockDepth; } + public BeginLockScopeNode(JavaKind kind, int lockDepth) { + super(TYPE, StampFactory.forKind(kind)); + this.lockDepth = lockDepth; + } + @Override public boolean hasSideEffect() { return false; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ComputeObjectAddressNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ComputeObjectAddressNode.java index bff064cfa38..b1fbaa0a564 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ComputeObjectAddressNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/ComputeObjectAddressNode.java @@ -22,12 +22,12 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodeinfo.NodeSize; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.debug.ControlFlowAnchored; @@ -40,7 +40,7 @@ import jdk.vm.ci.meta.JavaKind; * A high-level intrinsic for getting an address inside of an object. During lowering it will be * moved next to any uses to avoid creating a derived pointer that is live across a safepoint. */ -@NodeInfo(cycles = CYCLES_3, size = SIZE_2) +@NodeInfo(cycles = CYCLES_1, size = NodeSize.SIZE_1) public final class ComputeObjectAddressNode extends FixedWithNextNode implements Lowerable, ControlFlowAnchored { public static final NodeClass TYPE = NodeClass.create(ComputeObjectAddressNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java deleted file mode 100644 index 06a26f6f08b..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.hotspot.HotSpotBackend.FETCH_UNROLL_INFO; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; - -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.Value; - -/** - * A call to the runtime code {@code Deoptimization::fetch_unroll_info}. - */ -@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN) -public final class DeoptimizationFetchUnrollInfoCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { - - public static final NodeClass TYPE = NodeClass.create(DeoptimizationFetchUnrollInfoCallNode.class); - @Input SaveAllRegistersNode registerSaver; - @Input ValueNode mode; - protected final ForeignCallsProvider foreignCalls; - - public DeoptimizationFetchUnrollInfoCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode mode) { - super(TYPE, StampFactory.forKind(JavaKind.fromJavaClass(FETCH_UNROLL_INFO.getResultType()))); - this.registerSaver = (SaveAllRegistersNode) registerSaver; - this.mode = mode; - this.foreignCalls = foreignCalls; - } - - @Override - public LocationIdentity getLocationIdentity() { - return LocationIdentity.any(); - } - - public SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - /** - * Returns the node representing the exec_mode/unpack_kind used during this fetch_unroll_info - * call. - */ - public ValueNode getMode() { - return mode; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitDeoptimizationFetchUnrollInfoCall(gen.operand(getMode()), getSaveRegistersOp()); - gen.setResult(this, result); - } - - @NodeIntrinsic - public static native Word fetchUnrollInfo(long registerSaver, int mode); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizeCallerNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizeCallerNode.java index 09aa3e359e9..87982010819 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizeCallerNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizeCallerNode.java @@ -22,8 +22,8 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; @@ -39,7 +39,7 @@ import jdk.vm.ci.meta.DeoptimizationReason; /** * Removes the current frame and tail calls the uncommon trap routine. */ -@NodeInfo(shortName = "DeoptCaller", nameTemplate = "DeoptCaller {p#reason/s}", cycles = CYCLES_1, size = SIZE_3) +@NodeInfo(shortName = "DeoptCaller", nameTemplate = "DeoptCaller {p#reason/s}", cycles = CYCLES_8, size = SIZE_8) public final class DeoptimizeCallerNode extends ControlSinkNode implements LIRLowerable { public static final NodeClass TYPE = NodeClass.create(DeoptimizeCallerNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java index db08803de12..4c2f3782a91 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DimensionsNode.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.asm.NumUtil.roundUp; +import static org.graalvm.compiler.core.common.NumUtil.roundUp; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DirectCompareAndSwapNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DirectCompareAndSwapNode.java deleted file mode 100644 index 74eac1ede7e..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DirectCompareAndSwapNode.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.InputType.Association; -import static org.graalvm.compiler.nodeinfo.InputType.Memory; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_30; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; - -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotNodeLIRBuilder; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.StateSplit; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.java.CompareAndSwapNode; -import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; -import org.graalvm.compiler.nodes.memory.address.AddressNode; -import org.graalvm.compiler.nodes.memory.address.AddressNode.Address; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -/** - * A special purpose store node that differs from {@link CompareAndSwapNode} in that it is not a - * {@link StateSplit} and it {@linkplain #compareAndSwap(Address, Word, Word, LocationIdentity)} - * returns either the expected value or the compared against value instead of a boolean. - */ -@NodeInfo(allowedUsageTypes = Memory, cycles = CYCLES_30, size = SIZE_8) -public final class DirectCompareAndSwapNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { - - public static final NodeClass TYPE = NodeClass.create(DirectCompareAndSwapNode.class); - @Input(Association) AddressNode address; - @Input ValueNode expectedValue; - @Input ValueNode newValue; - - protected final LocationIdentity locationIdentity; - - public DirectCompareAndSwapNode(ValueNode address, ValueNode expected, ValueNode newValue, LocationIdentity locationIdentity) { - super(TYPE, expected.stamp()); - this.address = (AddressNode) address; - this.expectedValue = expected; - this.newValue = newValue; - this.locationIdentity = locationIdentity; - } - - public AddressNode getAddress() { - return address; - } - - public ValueNode expectedValue() { - return expectedValue; - } - - public ValueNode newValue() { - return newValue; - } - - @Override - public LocationIdentity getLocationIdentity() { - return locationIdentity; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - ((HotSpotNodeLIRBuilder) gen).visitDirectCompareAndSwap(this); - } - - /** - * Compares an expected value with the actual value in a location denoted by an address. Iff - * they are same, {@code newValue} is placed into the location and the {@code expectedValue} is - * returned. Otherwise, the actual value is returned. All of the above is performed in one - * atomic hardware transaction. - * - * @param address the address to be atomically tested and updated - * @param expectedValue if this value is currently in the field, perform the swap - * @param newValue the new value to put into the field - * @return either {@code expectedValue} or the actual value - */ - @NodeIntrinsic - public static native Word compareAndSwap(Address address, Word expectedValue, Word newValue, @ConstantNodeParameter LocationIdentity locationIdentity); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java index 53db7d9d1ae..0c12d547d83 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java @@ -26,7 +26,6 @@ import static org.graalvm.compiler.nodeinfo.InputType.Memory; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -35,6 +34,7 @@ import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint; import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.word.LocationIdentity; /** * Intrinsic for closing a {@linkplain BeginLockScopeNode scope} binding a stack-based lock with an diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EnterUnpackFramesStackFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EnterUnpackFramesStackFrameNode.java deleted file mode 100644 index 2685973c15e..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EnterUnpackFramesStackFrameNode.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_20; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_10; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.Value; - -/** - * Emits code to enter a low-level stack frame specifically to call out to the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@NodeInfo(cycles = CYCLES_20, size = SIZE_10) -public final class EnterUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { - public static final NodeClass TYPE = NodeClass.create(EnterUnpackFramesStackFrameNode.class); - - @Input ValueNode framePc; - @Input ValueNode senderSp; - @Input ValueNode senderFp; - @Input SaveAllRegistersNode registerSaver; - - public EnterUnpackFramesStackFrameNode(ValueNode framePc, ValueNode senderSp, ValueNode senderFp, ValueNode registerSaver) { - super(TYPE, StampFactory.forVoid()); - this.framePc = framePc; - this.senderSp = senderSp; - this.senderFp = senderFp; - this.registerSaver = (SaveAllRegistersNode) registerSaver; - } - - private SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value operandValue = gen.operand(framePc); - Value senderSpValue = gen.operand(senderSp); - Value senderFpValue = gen.operand(senderFp); - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitEnterUnpackFramesStackFrame(operandValue, senderSpValue, senderFpValue, getSaveRegistersOp()); - } - - @NodeIntrinsic - public static native void enterUnpackFramesStackFrame(Word framePc, Word senderSp, Word senderFp, long registerSaver); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java index 3254f6b082a..4759072762f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePostWriteBarrier.java @@ -22,14 +22,14 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_100; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_100; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; -@NodeInfo(cycles = CYCLES_100, size = SIZE_100) +@NodeInfo(cycles = CYCLES_64, size = SIZE_64) public class G1ArrayRangePostWriteBarrier extends ArrayRangeWriteBarrier { public static final NodeClass TYPE = NodeClass.create(G1ArrayRangePostWriteBarrier.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java index e290a14f778..a7b6cc8d47d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ArrayRangePreWriteBarrier.java @@ -22,14 +22,14 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_100; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_100; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; -@NodeInfo(cycles = CYCLES_100, size = SIZE_100) +@NodeInfo(cycles = CYCLES_64, size = SIZE_64) public final class G1ArrayRangePreWriteBarrier extends ArrayRangeWriteBarrier { public static final NodeClass TYPE = NodeClass.create(G1ArrayRangePreWriteBarrier.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PostWriteBarrier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PostWriteBarrier.java index d4a994cc8ca..522e20f9470 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PostWriteBarrier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PostWriteBarrier.java @@ -22,15 +22,15 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_50; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_50; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; -@NodeInfo(cycles = CYCLES_50, size = SIZE_50) +@NodeInfo(cycles = CYCLES_64, size = SIZE_64) public class G1PostWriteBarrier extends ObjectWriteBarrier { public static final NodeClass TYPE = NodeClass.create(G1PostWriteBarrier.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PreWriteBarrier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PreWriteBarrier.java index 4e21beb405c..521954be2dc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PreWriteBarrier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1PreWriteBarrier.java @@ -22,8 +22,8 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_50; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_50; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.InputType; @@ -33,7 +33,7 @@ import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; -@NodeInfo(cycles = CYCLES_50, size = SIZE_50) +@NodeInfo(cycles = CYCLES_64, size = SIZE_64) public final class G1PreWriteBarrier extends ObjectWriteBarrier implements DeoptimizingNode.DeoptBefore { public static final NodeClass TYPE = NodeClass.create(G1PreWriteBarrier.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ReferentFieldReadBarrier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ReferentFieldReadBarrier.java index bc59c044f24..26c3bb75715 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ReferentFieldReadBarrier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/G1ReferentFieldReadBarrier.java @@ -22,8 +22,8 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_50; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_50; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; @@ -36,7 +36,7 @@ import org.graalvm.compiler.nodes.memory.address.AddressNode; * {@code UnsafeLoadNode}). The return value of the read is passed to the snippet implementing the * read barrier and consequently is added to the SATB queue if the concurrent marker is enabled. */ -@NodeInfo(cycles = CYCLES_50, size = SIZE_50) +@NodeInfo(cycles = CYCLES_64, size = SIZE_64) public final class G1ReferentFieldReadBarrier extends ObjectWriteBarrier { public static final NodeClass TYPE = NodeClass.create(G1ReferentFieldReadBarrier.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java index 8d0575fe6b5..3287063e209 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/GraalHotSpotVMConfigNode.java @@ -29,6 +29,7 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -72,8 +73,8 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab * @param config * @param markId id of the config value */ - public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config, int markId) { - super(TYPE, StampFactory.forNodeIntrinsic()); + public GraalHotSpotVMConfigNode(@InjectedNodeParameter Stamp stamp, @InjectedNodeParameter GraalHotSpotVMConfig config, int markId) { + super(TYPE, stamp); this.config = config; this.markId = markId; } @@ -85,7 +86,7 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab * @param markId id of the config value * @param kind explicit type of the node */ - public GraalHotSpotVMConfigNode(@InjectedNodeParameter GraalHotSpotVMConfig config, int markId, JavaKind kind) { + public GraalHotSpotVMConfigNode(GraalHotSpotVMConfig config, int markId, JavaKind kind) { super(TYPE, StampFactory.forKind(kind)); this.config = config; this.markId = markId; @@ -100,13 +101,13 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab @NodeIntrinsic private static native boolean areConfigValuesConstant(); - @NodeIntrinsic(setStampFromReturnType = true) + @NodeIntrinsic private static native long loadLongConfigValue(@ConstantNodeParameter int markId); - @NodeIntrinsic(setStampFromReturnType = true) + @NodeIntrinsic private static native int loadIntConfigValue(@ConstantNodeParameter int markId); - @NodeIntrinsic(setStampFromReturnType = true) + @NodeIntrinsic private static native byte loadByteConfigValue(@ConstantNodeParameter int markId); public static long cardTableAddress() { @@ -170,20 +171,20 @@ public class GraalHotSpotVMConfigNode extends FloatingNode implements LIRLowerab @Override public Node canonical(CanonicalizerTool tool) { if (markId == 0) { - return ConstantNode.forBoolean(!GeneratePIC.getValue()); + return ConstantNode.forBoolean(!GeneratePIC.getValue(tool.getOptions())); } - if (!GeneratePIC.getValue()) { - if (markId == cardTableAddressMark(config)) { + if (!GeneratePIC.getValue(tool.getOptions())) { + if (markId == config.MARKID_CARD_TABLE_ADDRESS) { return ConstantNode.forLong(config.cardtableStartAddress); - } else if (markId == heapTopAddressMark(config)) { + } else if (markId == config.MARKID_HEAP_TOP_ADDRESS) { return ConstantNode.forLong(config.heapTopAddress); - } else if (markId == heapEndAddressMark(config)) { + } else if (markId == config.MARKID_HEAP_END_ADDRESS) { return ConstantNode.forLong(config.heapEndAddress); - } else if (markId == crcTableAddressMark(config)) { + } else if (markId == config.MARKID_CRC_TABLE_ADDRESS) { return ConstantNode.forLong(config.crcTableAddress); - } else if (markId == logOfHeapRegionGrainBytesMark(config)) { + } else if (markId == config.MARKID_LOG_OF_HEAP_REGION_GRAIN_BYTES) { return ConstantNode.forInt(config.logOfHRGrainBytes); - } else if (markId == inlineContiguousAllocationSupportedMark(config)) { + } else if (markId == config.MARKID_INLINE_CONTIGUOUS_ALLOCATION_SUPPORTED) { return ConstantNode.forBoolean(config.inlineContiguousAllocationSupported); } else { assert false; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotCompressionNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotCompressionNode.java new file mode 100644 index 00000000000..ecd8ba0b811 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotCompressionNode.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.nodes; + +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; + +import org.graalvm.compiler.core.common.CompressEncoding; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.hotspot.nodes.type.HotSpotNarrowOopStamp; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.CompressionNode; +import org.graalvm.compiler.nodes.ValueNode; + +import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; +import jdk.vm.ci.hotspot.HotSpotConstant; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; + +@NodeInfo(nameTemplate = "{p#op/s}", cycles = CYCLES_2, size = SIZE_2) +public final class HotSpotCompressionNode extends CompressionNode { + + public static final NodeClass TYPE = NodeClass.create(HotSpotCompressionNode.class); + + public HotSpotCompressionNode(CompressionOp op, ValueNode input, CompressEncoding encoding) { + super(TYPE, op, input, HotSpotNarrowOopStamp.mkStamp(op, input.stamp(), encoding), encoding); + } + + public static HotSpotCompressionNode compress(ValueNode input, CompressEncoding encoding) { + return input.graph().unique(new HotSpotCompressionNode(CompressionOp.Compress, input, encoding)); + } + + public static CompressionNode uncompress(ValueNode input, CompressEncoding encoding) { + return input.graph().unique(new HotSpotCompressionNode(CompressionOp.Uncompress, input, encoding)); + } + + @Override + protected Constant compress(Constant c) { + if (JavaConstant.NULL_POINTER.equals(c)) { + return HotSpotCompressedNullConstant.COMPRESSED_NULL; + } else if (c instanceof HotSpotConstant) { + return ((HotSpotConstant) c).compress(); + } else { + throw GraalError.shouldNotReachHere("invalid constant input for compress op: " + c); + } + } + + @Override + protected Constant uncompress(Constant c) { + if (c instanceof HotSpotConstant) { + return ((HotSpotConstant) c).uncompress(); + } else { + throw GraalError.shouldNotReachHere("invalid constant input for uncompress op: " + c); + } + } + + @Override + protected Stamp mkStamp(Stamp input) { + return HotSpotNarrowOopStamp.mkStamp(op, input, encoding); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotNodeCostProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotNodeCostProvider.java deleted file mode 100644 index 86785dd20d8..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/HotSpotNodeCostProvider.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_20; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_30; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_30; - -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.hotspot.replacements.ObjectCloneNode; -import org.graalvm.compiler.nodeinfo.NodeCycles; -import org.graalvm.compiler.nodeinfo.NodeSize; -import org.graalvm.compiler.nodes.spi.DefaultNodeCostProvider; -import org.graalvm.compiler.nodes.type.StampTool; - -import jdk.vm.ci.meta.ResolvedJavaType; - -public abstract class HotSpotNodeCostProvider extends DefaultNodeCostProvider { - - @Override - public NodeSize size(Node n) { - if (n instanceof ObjectCloneNode) { - ResolvedJavaType type = StampTool.typeOrNull(((ObjectCloneNode) n).getObject()); - if (type != null) { - if (type.isArray()) { - return SIZE_30; - } else { - return SIZE_20; - } - } - } - return super.size(n); - } - - @Override - public NodeCycles cycles(Node n) { - if (n instanceof ObjectCloneNode) { - ResolvedJavaType type = StampTool.typeOrNull(((ObjectCloneNode) n).getObject()); - if (type != null) { - if (type.isArray()) { - return CYCLES_30; - } else { - return CYCLES_20; - } - } - } - return super.cycles(n); - } - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java index de069c21fe8..1eee507fcdf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerInCallerNode.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_15; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; import org.graalvm.compiler.core.common.type.StampFactory; @@ -40,7 +40,7 @@ import org.graalvm.compiler.word.Word; * Sets up the {@linkplain HotSpotBackend#EXCEPTION_HANDLER_IN_CALLER arguments} expected by an * exception handler in the caller's frame, removes the current frame and jumps to said handler. */ -@NodeInfo(cycles = CYCLES_15, size = SIZE_8) +@NodeInfo(cycles = CYCLES_8, size = SIZE_8) public final class JumpToExceptionHandlerInCallerNode extends ControlSinkNode implements LIRLowerable { public static final NodeClass TYPE = NodeClass.create(JumpToExceptionHandlerInCallerNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerNode.java index f7ca42ff833..0a9a11d13dc 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/JumpToExceptionHandlerNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 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 diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveCurrentStackFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveCurrentStackFrameNode.java deleted file mode 100644 index 45e076f64e2..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveCurrentStackFrameNode.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_10; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_6; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; - -/** - * Emits code to leave (pop) the current low-level stack frame. This operation also removes the - * return address if its location is on the stack. - */ -@NodeInfo(cycles = CYCLES_10, size = SIZE_6) -public final class LeaveCurrentStackFrameNode extends FixedWithNextNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(LeaveCurrentStackFrameNode.class); - @Input SaveAllRegistersNode registerSaver; - - public LeaveCurrentStackFrameNode(ValueNode registerSaver) { - super(TYPE, StampFactory.forVoid()); - this.registerSaver = (SaveAllRegistersNode) registerSaver; - } - - private SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveCurrentStackFrame(getSaveRegistersOp()); - } - - @NodeIntrinsic - public static native void leaveCurrentStackFrame(long registerSaver); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java deleted file mode 100644 index 843dbc65947..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.hotspot.stubs.DeoptimizationStub; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.Value; - -/** - * Emits code to leave (pop) the current low-level stack frame which is being deoptimized. This node - * is only used in {@link DeoptimizationStub}. - */ -@NodeInfo(cycles = CYCLES_3, size = SIZE_2) -public final class LeaveDeoptimizedStackFrameNode extends FixedWithNextNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(LeaveDeoptimizedStackFrameNode.class); - @Input ValueNode frameSize; - @Input ValueNode initialInfo; - - public LeaveDeoptimizedStackFrameNode(ValueNode frameSize, ValueNode initialInfo) { - super(TYPE, StampFactory.forVoid()); - this.frameSize = frameSize; - this.initialInfo = initialInfo; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value frameSizeValue = gen.operand(frameSize); - Value initialInfoValue = gen.operand(initialInfo); - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveDeoptimizedStackFrame(frameSizeValue, initialInfoValue); - } - - @NodeIntrinsic - public static native void leaveDeoptimizedStackFrame(int frameSize, Word initialInfo); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java deleted file mode 100644 index 2c54a4a2c83..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_10; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_6; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotBackend; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; - -/** - * Emits code to leave a low-level stack frame specifically to call out to the C++ method - * {@link HotSpotBackend#UNPACK_FRAMES Deoptimization::unpack_frames}. - */ -@NodeInfo(cycles = CYCLES_10, size = SIZE_6) -public final class LeaveUnpackFramesStackFrameNode extends FixedWithNextNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(LeaveUnpackFramesStackFrameNode.class); - @Input SaveAllRegistersNode registerSaver; - - public LeaveUnpackFramesStackFrameNode(ValueNode registerSaver) { - super(TYPE, StampFactory.forVoid()); - this.registerSaver = (SaveAllRegistersNode) registerSaver; - } - - private SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitLeaveUnpackFramesStackFrame(getSaveRegistersOp()); - } - - @NodeIntrinsic - public static native void leaveUnpackFramesStackFrame(long registerSaver); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/PushInterpreterFrameNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/PushInterpreterFrameNode.java deleted file mode 100644 index e779da57db9..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/PushInterpreterFrameNode.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_6; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.Value; - -/** - * A call to the runtime code implementing the uncommon trap logic. - */ -@NodeInfo(cycles = CYCLES_8, size = SIZE_6) -public final class PushInterpreterFrameNode extends FixedWithNextNode implements LIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(PushInterpreterFrameNode.class); - @Input ValueNode framePc; - @Input ValueNode frameSize; - @Input ValueNode senderSp; - @Input ValueNode initialInfo; - - public PushInterpreterFrameNode(ValueNode frameSize, ValueNode framePc, ValueNode senderSp, ValueNode initialInfo) { - super(TYPE, StampFactory.forVoid()); - this.frameSize = frameSize; - this.framePc = framePc; - this.senderSp = senderSp; - this.initialInfo = initialInfo; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value frameSizeValue = gen.operand(frameSize); - Value framePcValue = gen.operand(framePc); - Value senderSpValue = gen.operand(senderSp); - Value initialInfoValue = gen.operand(initialInfo); - ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitPushInterpreterFrame(frameSizeValue, framePcValue, senderSpValue, initialInfoValue); - } - - @NodeIntrinsic - public static native void pushInterpreterFrame(Word frameSize, Word framePc, Word senderSp, Word initialInfo); - -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SaveAllRegistersNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SaveAllRegistersNode.java deleted file mode 100644 index e0a25037e31..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SaveAllRegistersNode.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import jdk.vm.ci.meta.JavaKind; - -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; - -/** - * Saves all allocatable registers. - */ -@NodeInfo(allowedUsageTypes = {InputType.Memory}) -public final class SaveAllRegistersNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { - - public static final NodeClass TYPE = NodeClass.create(SaveAllRegistersNode.class); - protected SaveRegistersOp saveRegistersOp; - - public SaveAllRegistersNode() { - super(TYPE, StampFactory.forKind(JavaKind.Long)); - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - saveRegistersOp = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitSaveAllRegisters(); - } - - /** - * @return the map from registers to the stack locations in they are saved - */ - public SaveRegistersOp getSaveRegistersOp() { - assert saveRegistersOp != null : "saved registers op has not yet been created"; - return saveRegistersOp; - } - - /** - * @return a token that couples this node to an {@link UncommonTrapCallNode} so that the latter - * has access to the {@linkplain SaveRegistersOp#getMap register save map} - */ - @NodeIntrinsic - public static native long saveAllRegisters(); - - @Override - public LocationIdentity getLocationIdentity() { - return LocationIdentity.any(); - } -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java index ba95b819b91..29da335efa6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialArrayRangeWriteBarrier.java @@ -22,14 +22,14 @@ */ package org.graalvm.compiler.hotspot.nodes; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_15; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ValueNode; -@NodeInfo(cycles = CYCLES_15, size = SIZE_20) +@NodeInfo(cycles = CYCLES_8, size = SIZE_8) public final class SerialArrayRangeWriteBarrier extends ArrayRangeWriteBarrier { public static final NodeClass TYPE = NodeClass.create(SerialArrayRangeWriteBarrier.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialWriteBarrier.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialWriteBarrier.java index cf03b16b8e4..608b9b4c3dd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialWriteBarrier.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SerialWriteBarrier.java @@ -23,13 +23,13 @@ package org.graalvm.compiler.hotspot.nodes; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.memory.address.AddressNode; -@NodeInfo(cycles = CYCLES_8, size = SIZE_3) +@NodeInfo(cycles = CYCLES_8, size = SIZE_4) public class SerialWriteBarrier extends ObjectWriteBarrier { public static final NodeClass TYPE = NodeClass.create(SerialWriteBarrier.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SnippetLocationProxyNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SnippetLocationProxyNode.java deleted file mode 100644 index 061dc110df3..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SnippetLocationProxyNode.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; - -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.graph.spi.Canonicalizable; -import org.graalvm.compiler.graph.spi.CanonicalizerTool; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.FloatingNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; - -@NodeInfo(allowedUsageTypes = {InputType.Association, InputType.Value}, cycles = CYCLES_0, size = SIZE_0) -public final class SnippetLocationProxyNode extends FloatingNode implements Canonicalizable, Node.ValueNumberable { - - public static final NodeClass TYPE = NodeClass.create(SnippetLocationProxyNode.class); - @Input(InputType.Unchecked) ValueNode location; - - public SnippetLocationProxyNode(ValueNode location) { - super(TYPE, StampFactory.object()); - this.location = location; - } - - @Override - public Node canonical(CanonicalizerTool tool) { - return location.isAllowedUsageType(InputType.Association) ? location : this; - } - - @NodeIntrinsic - public static native GuardingNode location(Object location); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java index 3d285fcfce6..a7e28a9dcb6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java @@ -28,11 +28,10 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; import java.util.Arrays; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; -import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.NodeInputList; import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil; @@ -43,8 +42,8 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.word.LocationIdentity; -import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.Value; /** @@ -59,8 +58,8 @@ public final class StubForeignCallNode extends FixedWithNextNode implements LIRL protected final ForeignCallDescriptor descriptor; - public StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ForeignCallDescriptor descriptor, ValueNode... arguments) { - super(TYPE, StampFactory.forKind(JavaKind.fromJavaClass(descriptor.getResultType()))); + public StubForeignCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, @InjectedNodeParameter Stamp stamp, ForeignCallDescriptor descriptor, ValueNode... arguments) { + super(TYPE, stamp); this.arguments = new NodeInputList<>(this, arguments); this.descriptor = descriptor; this.foreignCalls = foreignCalls; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/UncommonTrapCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/UncommonTrapCallNode.java deleted file mode 100644 index 2cee5fc0185..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/UncommonTrapCallNode.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.nodes; - -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNCOMMON_TRAP; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; - -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.graph.NodeClass; -import org.graalvm.compiler.hotspot.HotSpotLIRGenerator; -import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; -import org.graalvm.compiler.nodeinfo.InputType; -import org.graalvm.compiler.nodeinfo.NodeInfo; -import org.graalvm.compiler.nodes.FixedWithNextNode; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; -import org.graalvm.compiler.nodes.spi.LIRLowerable; -import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.Value; - -/** - * A call to the runtime code implementing the uncommon trap logic. - */ -@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_UNKNOWN) -public final class UncommonTrapCallNode extends FixedWithNextNode implements LIRLowerable, MemoryCheckpoint.Single { - - public static final NodeClass TYPE = NodeClass.create(UncommonTrapCallNode.class); - @Input ValueNode trapRequest; - @Input ValueNode mode; - @Input SaveAllRegistersNode registerSaver; - protected final ForeignCallsProvider foreignCalls; - - public UncommonTrapCallNode(@InjectedNodeParameter ForeignCallsProvider foreignCalls, ValueNode registerSaver, ValueNode trapRequest, ValueNode mode) { - super(TYPE, StampFactory.forKind(JavaKind.fromJavaClass(UNCOMMON_TRAP.getResultType()))); - this.trapRequest = trapRequest; - this.mode = mode; - this.registerSaver = (SaveAllRegistersNode) registerSaver; - this.foreignCalls = foreignCalls; - } - - @Override - public LocationIdentity getLocationIdentity() { - return LocationIdentity.any(); - } - - public SaveRegistersOp getSaveRegistersOp() { - return registerSaver.getSaveRegistersOp(); - } - - /** - * Returns the node representing the exec_mode/unpack_kind used during this fetch_unroll_info - * call. - */ - public ValueNode getMode() { - return mode; - } - - @Override - public void generate(NodeLIRBuilderTool gen) { - Value trapRequestValue = gen.operand(trapRequest); - Value modeValue = gen.operand(getMode()); - Value result = ((HotSpotLIRGenerator) gen.getLIRGeneratorTool()).emitUncommonTrapCall(trapRequestValue, modeValue, getSaveRegistersOp()); - gen.setResult(this, result); - } - - @NodeIntrinsic - public static native Word uncommonTrap(long registerSaver, int trapRequest, int mode); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java index 31cbf052bdb..b6905996f69 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/EncodedSymbolNode.java @@ -22,6 +22,10 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; + +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -37,15 +41,15 @@ import org.graalvm.compiler.word.Word; import jdk.vm.ci.meta.Constant; -@NodeInfo +@NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED) public final class EncodedSymbolNode extends FloatingNode implements Canonicalizable { public static final NodeClass TYPE = NodeClass.create(EncodedSymbolNode.class); @OptionalInput protected ValueNode value; - public EncodedSymbolNode(ValueNode value) { - super(TYPE, null); + public EncodedSymbolNode(@InjectedNodeParameter Stamp stamp, ValueNode value) { + super(TYPE, stamp); assert value != null; this.value = value; } @@ -61,6 +65,6 @@ public final class EncodedSymbolNode extends FloatingNode implements Canonicaliz return this; } - @NodeIntrinsic(setStampFromReturnType = true) + @NodeIntrinsic public static native Word encode(Object constant); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java index 48acc4c080e..aff5ce9b872 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java @@ -22,18 +22,21 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; +import static org.graalvm.compiler.nodeinfo.InputType.Memory; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.word.LocationIdentity; -@NodeInfo(cycles = CYCLES_3, size = SIZE_20) -public class InitializeKlassNode extends DeoptimizingFixedWithNextNode implements Lowerable { +@NodeInfo(cycles = CYCLES_4, size = SIZE_16, allowedUsageTypes = {Memory}) +public class InitializeKlassNode extends DeoptimizingFixedWithNextNode implements Lowerable, MemoryCheckpoint.Single { public static final NodeClass TYPE = NodeClass.create(InitializeKlassNode.class); @Input ValueNode value; @@ -56,4 +59,9 @@ public class InitializeKlassNode extends DeoptimizingFixedWithNextNode implement public boolean canDeoptimize() { return true; } + + @Override + public LocationIdentity getLocationIdentity() { + return LocationIdentity.any(); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java index 03d11fa9107..2630a60dcd3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java @@ -23,9 +23,8 @@ package org.graalvm.compiler.hotspot.nodes.aot; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -43,6 +42,7 @@ import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.meta.Constant; @@ -51,7 +51,7 @@ import jdk.vm.ci.meta.Value; /** * A call to the VM via a regular stub. */ -@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_20) +@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_UNKNOWN, size = SIZE_16) public class InitializeKlassStubCall extends AbstractMemoryCheckpoint implements LIRLowerable, Canonicalizable, DeoptimizingNode.DeoptBefore, MemoryCheckpoint.Single { public static final NodeClass TYPE = NodeClass.create(InitializeKlassStubCall.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java index 257fc5a7fca..2603e78cee4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyFixedNode.java @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -46,7 +46,7 @@ import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.Value; -@NodeInfo(cycles = CYCLES_3, size = SIZE_3) +@NodeInfo(cycles = CYCLES_4, size = SIZE_1) public class LoadConstantIndirectlyFixedNode extends FixedWithNextNode implements Canonicalizable, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(LoadConstantIndirectlyFixedNode.class); @@ -56,14 +56,14 @@ public class LoadConstantIndirectlyFixedNode extends FixedWithNextNode implement protected HotSpotConstantLoadAction action; public LoadConstantIndirectlyFixedNode(ValueNode value) { - super(TYPE, value.stamp().unrestricted()); + super(TYPE, value.stamp()); this.value = value; this.constant = null; this.action = HotSpotConstantLoadAction.RESOLVE; } public LoadConstantIndirectlyFixedNode(ValueNode value, HotSpotConstantLoadAction action) { - super(TYPE, value.stamp().unrestricted()); + super(TYPE, value.stamp()); this.value = value; this.constant = null; this.action = action; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java index 10c3c9337aa..8758c02cba3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadConstantIndirectlyNode.java @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -45,7 +45,7 @@ import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.Value; -@NodeInfo(cycles = CYCLES_3, size = SIZE_3) +@NodeInfo(cycles = CYCLES_4, size = SIZE_1) public class LoadConstantIndirectlyNode extends FloatingNode implements Canonicalizable, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(LoadConstantIndirectlyNode.class); @@ -55,14 +55,14 @@ public class LoadConstantIndirectlyNode extends FloatingNode implements Canonica protected HotSpotConstantLoadAction action; public LoadConstantIndirectlyNode(ValueNode value) { - super(TYPE, value.stamp().unrestricted()); + super(TYPE, value.stamp()); this.value = value; this.constant = null; this.action = HotSpotConstantLoadAction.RESOLVE; } public LoadConstantIndirectlyNode(ValueNode value, HotSpotConstantLoadAction action) { - super(TYPE, value.stamp().unrestricted()); + super(TYPE, value.stamp()); this.value = value; this.constant = null; this.action = action; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java index 1b8180b082c..dd427b1772a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersIndirectlyNode.java @@ -22,10 +22,10 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -46,7 +46,7 @@ import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.Value; -@NodeInfo(cycles = CYCLES_3, size = SIZE_3) +@NodeInfo(cycles = CYCLES_4, size = SIZE_4) public class LoadMethodCountersIndirectlyNode extends FloatingNode implements Canonicalizable, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(LoadMethodCountersIndirectlyNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersNode.java index 290de38a039..f9ebc380e18 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/LoadMethodCountersNode.java @@ -22,10 +22,8 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_3; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_4; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.NodeClass; @@ -37,7 +35,9 @@ import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; -@NodeInfo(cycles = CYCLES_3, size = SIZE_3) +import jdk.vm.ci.meta.ResolvedJavaMethod; + +@NodeInfo(cycles = CYCLES_4, size = SIZE_4) public class LoadMethodCountersNode extends FloatingNode implements LIRLowerable { public static final NodeClass TYPE = NodeClass.create(LoadMethodCountersNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java index 17a3e0e6a9e..73202626047 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java @@ -22,19 +22,19 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; -@NodeInfo(cycles = CYCLES_3, size = SIZE_20) -public class ResolveConstantNode extends FloatingNode implements Lowerable { +@NodeInfo(cycles = CYCLES_4, size = SIZE_16) +public class ResolveConstantNode extends DeoptimizingFixedWithNextNode implements Lowerable { public static final NodeClass TYPE = NodeClass.create(ResolveConstantNode.class); @Input ValueNode value; @@ -64,4 +64,9 @@ public class ResolveConstantNode extends FloatingNode implements Lowerable { public HotSpotConstantLoadAction action() { return action; } + + @Override + public boolean canDeoptimize() { + return true; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java index 017feacf64d..6a6393b1990 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java @@ -23,9 +23,9 @@ package org.graalvm.compiler.hotspot.nodes.aot; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -49,7 +49,7 @@ import jdk.vm.ci.meta.Value; /** * A call to the VM via a regular stub. */ -@NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_20) +@NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_16) public class ResolveConstantStubCall extends DeoptimizingStubCall implements Canonicalizable, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(ResolveConstantStubCall.class); @@ -110,5 +110,4 @@ public class ResolveConstantStubCall extends DeoptimizingStubCall implements Can } gen.setResult(this, result); } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java index 6561da24de9..78458f26b38 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java @@ -22,21 +22,21 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.nodes.type.MethodCountersPointerStamp; import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; -@NodeInfo(cycles = CYCLES_3, size = SIZE_20) -public class ResolveMethodAndLoadCountersNode extends FloatingNode implements Lowerable { +import jdk.vm.ci.meta.ResolvedJavaMethod; + +@NodeInfo(cycles = CYCLES_4, size = SIZE_16) +public class ResolveMethodAndLoadCountersNode extends DeoptimizingFixedWithNextNode implements Lowerable { public static final NodeClass TYPE = NodeClass.create(ResolveMethodAndLoadCountersNode.class); ResolvedJavaMethod method; @@ -60,4 +60,9 @@ public class ResolveMethodAndLoadCountersNode extends FloatingNode implements Lo public ValueNode getHub() { return hub; } + + @Override + public boolean canDeoptimize() { + return true; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersStubCall.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersStubCall.java index faa0bd095a0..725e3736d8c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersStubCall.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersStubCall.java @@ -22,11 +22,8 @@ */ package org.graalvm.compiler.hotspot.nodes.aot; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.Value; - import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; @@ -45,10 +42,13 @@ import org.graalvm.compiler.nodes.spi.LIRLowerable; import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.Value; + /** * A call to the VM via a regular stub. */ -@NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_20) +@NodeInfo(cycles = CYCLES_UNKNOWN, size = SIZE_16) public class ResolveMethodAndLoadCountersStubCall extends DeoptimizingStubCall implements Canonicalizable, LIRLowerable { public static final NodeClass TYPE = NodeClass.create(ResolveMethodAndLoadCountersStubCall.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java index 9d5e015bf4c..c5c09718e6b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileNode.java @@ -22,7 +22,8 @@ */ package org.graalvm.compiler.hotspot.nodes.profiling; -import jdk.vm.ci.meta.ResolvedJavaMethod; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; @@ -34,14 +35,16 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; -@NodeInfo +import jdk.vm.ci.meta.ResolvedJavaMethod; + +@NodeInfo(cycles = CYCLES_IGNORED, cyclesRationale = "profiling should be ignored", size = SIZE_IGNORED, sizeRationale = "profiling should be ignored") public class ProfileNode extends DeoptimizingFixedWithNextNode implements Lowerable { public static class Options { @Option(help = "Control probabilistic profiling on AMD64", type = OptionType.Expert)// - public static final OptionValue ProbabilisticProfiling = new OptionValue<>(true); + public static final OptionKey ProbabilisticProfiling = new OptionKey<>(true); } public static final NodeClass TYPE = NodeClass.create(ProfileNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileWithNotificationNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileWithNotificationNode.java index 4d63dea4a5d..d0fdcbc2867 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileWithNotificationNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/profiling/ProfileWithNotificationNode.java @@ -22,15 +22,12 @@ */ package org.graalvm.compiler.hotspot.nodes.profiling; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_10; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_50; - import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; -@NodeInfo(cycles = CYCLES_10, size = SIZE_50) +import jdk.vm.ci.meta.ResolvedJavaMethod; + +@NodeInfo public class ProfileWithNotificationNode extends ProfileNode { public static final NodeClass TYPE = NodeClass.create(ProfileWithNotificationNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/HotSpotNarrowOopStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/HotSpotNarrowOopStamp.java new file mode 100644 index 00000000000..ae4e255de7e --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/HotSpotNarrowOopStamp.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.hotspot.nodes.type; + +import org.graalvm.compiler.core.common.CompressEncoding; +import org.graalvm.compiler.core.common.type.AbstractObjectStamp; +import org.graalvm.compiler.core.common.type.ObjectStamp; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.nodes.CompressionNode.CompressionOp; +import org.graalvm.compiler.nodes.type.NarrowOopStamp; + +import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; +import jdk.vm.ci.hotspot.HotSpotMemoryAccessProvider; +import jdk.vm.ci.hotspot.HotSpotObjectConstant; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.MemoryAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaType; + +public final class HotSpotNarrowOopStamp extends NarrowOopStamp { + private HotSpotNarrowOopStamp(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull, CompressEncoding encoding) { + super(type, exactType, nonNull, alwaysNull, encoding); + } + + @Override + protected AbstractObjectStamp copyWith(ResolvedJavaType type, boolean exactType, boolean nonNull, boolean alwaysNull) { + return new HotSpotNarrowOopStamp(type, exactType, nonNull, alwaysNull, getEncoding()); + } + + public static Stamp compressed(AbstractObjectStamp stamp, CompressEncoding encoding) { + return new HotSpotNarrowOopStamp(stamp.type(), stamp.isExactType(), stamp.nonNull(), stamp.alwaysNull(), encoding); + } + + @Override + public Constant readConstant(MemoryAccessProvider provider, Constant base, long displacement) { + try { + HotSpotMemoryAccessProvider hsProvider = (HotSpotMemoryAccessProvider) provider; + return hsProvider.readNarrowOopConstant(base, displacement); + } catch (IllegalArgumentException e) { + return null; + } + } + + @Override + public JavaConstant asConstant() { + if (alwaysNull()) { + return HotSpotCompressedNullConstant.COMPRESSED_NULL; + } else { + return null; + } + } + + @Override + public boolean isCompatible(Constant other) { + if (other instanceof HotSpotObjectConstant) { + return ((HotSpotObjectConstant) other).isCompressed(); + } + return true; + } + + public static Stamp mkStamp(CompressionOp op, Stamp input, CompressEncoding encoding) { + switch (op) { + case Compress: + if (input instanceof ObjectStamp) { + // compressed oop + return HotSpotNarrowOopStamp.compressed((ObjectStamp) input, encoding); + } else if (input instanceof KlassPointerStamp) { + // compressed klass pointer + return ((KlassPointerStamp) input).compressed(encoding); + } + break; + case Uncompress: + if (input instanceof NarrowOopStamp) { + // oop + assert encoding.equals(((NarrowOopStamp) input).getEncoding()); + return ((NarrowOopStamp) input).uncompressed(); + } else if (input instanceof KlassPointerStamp) { + // metaspace pointer + assert encoding.equals(((KlassPointerStamp) input).getEncoding()); + return ((KlassPointerStamp) input).uncompressed(); + } + break; + } + throw GraalError.shouldNotReachHere(String.format("Unexpected input stamp %s", input)); + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/KlassPointerStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/KlassPointerStamp.java index 51ef44ea120..b5af57d0251 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/KlassPointerStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/KlassPointerStamp.java @@ -24,11 +24,11 @@ package org.graalvm.compiler.hotspot.nodes.type; import java.util.Objects; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.spi.LIRKindTool; import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.hotspot.CompressEncoding; import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; import jdk.vm.ci.hotspot.HotSpotMemoryAccessProvider; @@ -131,7 +131,7 @@ public final class KlassPointerStamp extends MetaspacePointerStamp { @Override public LIRKind getLIRKind(LIRKindTool tool) { if (isCompressed()) { - return ((HotSpotLIRKindTool) tool).getNarrowPointerKind(); + return tool.getNarrowPointerKind(); } else { return super.getLIRKind(tool); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/MetaspacePointerStamp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/MetaspacePointerStamp.java index 4db514de7e1..53a2298fb81 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/MetaspacePointerStamp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/type/MetaspacePointerStamp.java @@ -59,6 +59,11 @@ public abstract class MetaspacePointerStamp extends AbstractPointerStamp { return true; } + @Override + public Stamp join(Stamp other) { + return defaultPointerJoin(other); + } + @Override public ResolvedJavaType javaType(MetaAccessProvider metaAccess) { throw GraalError.shouldNotReachHere("metaspace pointer has no Java type"); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java index bb5d0f71bdd..ff0ac313979 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/LoadJavaMirrorWithKlassPhase.java @@ -22,19 +22,20 @@ */ package org.graalvm.compiler.hotspot.phases; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_MIRROR_LOCATION; import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; import static org.graalvm.compiler.nodes.NamedLocationIdentity.FINAL_LOCATION; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.type.AbstractObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.hotspot.CompressEncoding; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode; +import org.graalvm.compiler.hotspot.nodes.type.HotSpotNarrowOopStamp; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; -import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp; +import org.graalvm.compiler.hotspot.replacements.HubGetClassNode; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -67,12 +68,10 @@ import jdk.vm.ci.meta.ResolvedJavaType; */ public class LoadJavaMirrorWithKlassPhase extends BasePhase { - private final int classMirrorOffset; private final CompressEncoding oopEncoding; - public LoadJavaMirrorWithKlassPhase(int classMirrorOffset, CompressEncoding oopEncoding) { - this.classMirrorOffset = classMirrorOffset; - this.oopEncoding = oopEncoding; + public LoadJavaMirrorWithKlassPhase(GraalHotSpotVMConfig config) { + this.oopEncoding = config.useCompressedOops ? config.getOopEncoding() : null; } private ValueNode getClassConstantReplacement(StructuredGraph graph, PhaseContext context, JavaConstant constant) { @@ -85,13 +84,12 @@ public class LoadJavaMirrorWithKlassPhase extends BasePhase { if (type instanceof HotSpotResolvedObjectType) { ConstantNode klass = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) type).klass(), metaAccess, graph); - AddressNode address = graph.unique(new OffsetAddressNode(klass, ConstantNode.forLong(classMirrorOffset, graph))); - ValueNode read = graph.unique(new FloatingReadNode(address, CLASS_MIRROR_LOCATION, null, stamp)); + ValueNode getClass = graph.unique(new HubGetClassNode(metaAccess, klass)); if (((HotSpotObjectConstant) constant).isCompressed()) { - return CompressionNode.compress(read, oopEncoding); + return HotSpotCompressionNode.compress(getClass, oopEncoding); } else { - return read; + return getClass; } } else { /* @@ -114,7 +112,7 @@ public class LoadJavaMirrorWithKlassPhase extends BasePhase { } if (oopEncoding != null) { - stamp = NarrowOopStamp.compressed((AbstractObjectStamp) stamp, oopEncoding); + stamp = HotSpotNarrowOopStamp.compressed((AbstractObjectStamp) stamp, oopEncoding); } AddressNode address = graph.unique(new OffsetAddressNode(clazz, ConstantNode.forLong(typeField.offset(), graph))); ValueNode read = graph.unique(new FloatingReadNode(address, FINAL_LOCATION, null, stamp)); @@ -122,7 +120,7 @@ public class LoadJavaMirrorWithKlassPhase extends BasePhase { if (oopEncoding == null || ((HotSpotObjectConstant) constant).isCompressed()) { return read; } else { - return CompressionNode.uncompress(read, oopEncoding); + return HotSpotCompressionNode.uncompress(read, oopEncoding); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java index 84f0f33ecb5..df14d7adc37 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java @@ -24,9 +24,11 @@ package org.graalvm.compiler.hotspot.phases; import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.cfg.Loop; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.iterators.NodeIterable; @@ -35,17 +37,30 @@ import org.graalvm.compiler.loop.phases.LoopTransformations; import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.AbstractLocalNode; import org.graalvm.compiler.nodes.EntryMarkerNode; import org.graalvm.compiler.nodes.EntryProxyNode; import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StartNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.extended.OSRLocalNode; +import org.graalvm.compiler.nodes.extended.OSRLockNode; +import org.graalvm.compiler.nodes.extended.OSRMonitorEnterNode; import org.graalvm.compiler.nodes.extended.OSRStartNode; +import org.graalvm.compiler.nodes.java.AccessMonitorNode; +import org.graalvm.compiler.nodes.java.MonitorEnterNode; +import org.graalvm.compiler.nodes.java.MonitorExitNode; +import org.graalvm.compiler.nodes.java.MonitorIdNode; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; +import org.graalvm.compiler.options.OptionType; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase; @@ -53,18 +68,56 @@ import jdk.vm.ci.runtime.JVMCICompiler; public class OnStackReplacementPhase extends Phase { + public static class Options { + // @formatter:off + @Option(help = "Deoptimize OSR compiled code when the OSR entry loop is finished " + + "if there is no mature profile available for the rest of the method.", type = OptionType.Debug) + public static final OptionKey DeoptAfterOSR = new OptionKey<>(true); + @Option(help = "Support OSR compilations with locks. If DeoptAfterOSR is true we can per definition not have " + + "unbalaced enter/extis mappings. If DeoptAfterOSR is false insert artificial monitor enters after " + + "the OSRStart to have balanced enter/exits in the graph.", type = OptionType.Debug) + public static final OptionKey SupportOSRWithLocks = new OptionKey<>(true); + // @formatter:on + } + + private static final CounterKey OsrWithLocksCount = DebugContext.counter("OSRWithLocks"); + + private static boolean supportOSRWithLocks(OptionValues options) { + return Options.SupportOSRWithLocks.getValue(options); + } + @Override protected void run(StructuredGraph graph) { + DebugContext debug = graph.getDebug(); if (graph.getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI) { // This happens during inlining in a OSR method, because the same phase plan will be // used. assert graph.getNodes(EntryMarkerNode.TYPE).isEmpty(); return; } - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement initial"); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement initial at bci %d", graph.getEntryBCI()); + EntryMarkerNode osr; int maxIterations = -1; int iterations = 0; + + final EntryMarkerNode originalOSRNode = getEntryMarker(graph); + final LoopBeginNode originalOSRLoop = osrLoop(originalOSRNode); + final boolean currentOSRWithLocks = osrWithLocks(originalOSRNode); + + if (originalOSRLoop == null) { + /* + * OSR with Locks: We do not have an OSR loop for the original OSR bci. Therefore we + * cannot decide where to deopt and which framestate will be used. In the worst case the + * framestate of the OSR entry would be used. + */ + throw new PermanentBailoutException("OSR compilation without OSR entry loop."); + } + + if (!supportOSRWithLocks(graph.getOptions()) && currentOSRWithLocks) { + throw new PermanentBailoutException("OSR with locks disabled."); + } + do { osr = getEntryMarker(graph); LoopsData loops = new LoopsData(graph); @@ -73,6 +126,7 @@ public class OnStackReplacementPhase extends Phase { if (l == null) { break; } + iterations++; if (maxIterations == -1) { maxIterations = l.getDepth(); @@ -91,7 +145,7 @@ public class OnStackReplacementPhase extends Phase { proxy.replaceAndDelete(proxy.value()); } GraphUtil.removeFixedWithUnusedInputs(osr); - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement loop peeling result"); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement loop peeling result"); } while (true); FrameState osrState = osr.stateAfter(); @@ -104,26 +158,81 @@ public class OnStackReplacementPhase extends Phase { graph.setStart(osrStart); osrStart.setStateAfter(osrState); - for (int i = 0; i < osrState.localsSize(); i++) { - ValueNode value = osrState.localAt(i); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement after setting OSR start"); + final int localsSize = osrState.localsSize(); + final int locksSize = osrState.locksSize(); + + for (int i = 0; i < localsSize + locksSize; i++) { + ValueNode value = null; + if (i >= localsSize) { + value = osrState.lockAt(i - localsSize); + } else { + value = osrState.localAt(i); + } if (value instanceof EntryProxyNode) { EntryProxyNode proxy = (EntryProxyNode) value; /* * we need to drop the stamp since the types we see during OSR may be too precise * (if a branch was not parsed for example). */ - proxy.replaceAndDelete(graph.addOrUnique(new OSRLocalNode(i, proxy.stamp().unrestricted()))); + Stamp s = proxy.stamp().unrestricted(); + AbstractLocalNode osrLocal = null; + if (i >= localsSize) { + osrLocal = graph.addOrUnique(new OSRLockNode(i - localsSize, s)); + } else { + osrLocal = graph.addOrUnique(new OSRLocalNode(i, s)); + } + proxy.replaceAndDelete(osrLocal); } else { assert value == null || value instanceof OSRLocalNode; } } + osr.replaceAtUsages(InputType.Guard, osrStart); - assert osr.usages().isEmpty(); - + debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement after replacing entry proxies"); GraphUtil.killCFG(start); - - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "OnStackReplacement result"); + debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement result"); new DeadCodeEliminationPhase(Required).apply(graph); + + if (currentOSRWithLocks) { + OsrWithLocksCount.increment(debug); + for (int i = osrState.monitorIdCount() - 1; i >= 0; --i) { + MonitorIdNode id = osrState.monitorIdAt(i); + ValueNode lockedObject = osrState.lockAt(i); + OSRMonitorEnterNode osrMonitorEnter = graph.add(new OSRMonitorEnterNode(lockedObject, id)); + for (Node usage : id.usages()) { + if (usage instanceof AccessMonitorNode) { + AccessMonitorNode access = (AccessMonitorNode) usage; + access.setObject(lockedObject); + } + } + FixedNode oldNext = osrStart.next(); + oldNext.replaceAtPredecessor(null); + osrMonitorEnter.setNext(oldNext); + osrStart.setNext(osrMonitorEnter); + } + debug.dump(DebugContext.DETAILED_LEVEL, graph, "After inserting OSR monitor enters"); + /* + * Ensure balanced monitorenter - monitorexit + * + * Ensure that there is no monitor exit without a monitor enter in the graph. If there + * is one this can only be done by bytecode as we have the monitor enter before the OSR + * loop but the exit in a path of the loop that must be under a condition, else it will + * throw an IllegalStateException anyway in the 2.iteration + */ + for (MonitorExitNode exit : graph.getNodes(MonitorExitNode.TYPE)) { + MonitorIdNode id = exit.getMonitorId(); + if (id.usages().filter(MonitorEnterNode.class).count() != 1) { + throw new PermanentBailoutException("Unbalanced monitor enter-exit in OSR compilation with locks. Object is locked before the loop but released inside the loop."); + } + } + } + debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement result"); + new DeadCodeEliminationPhase(Required).apply(graph); + /* + * There must not be any parameter nodes left after OSR compilation. + */ + assert graph.getNodes(ParameterNode.TYPE).count() == 0 : "OSR Compilation contains references to parameters."; } private static EntryMarkerNode getEntryMarker(StructuredGraph graph) { @@ -135,15 +244,26 @@ public class OnStackReplacementPhase extends Phase { if (osrNodes.count() > 1) { throw new GraalError("Multiple OnStackReplacementNodes generated"); } - if (osr.stateAfter().locksSize() != 0) { - throw new PermanentBailoutException("OSR with locks not supported"); - } if (osr.stateAfter().stackSize() != 0) { throw new PermanentBailoutException("OSR with stack entries not supported: %s", osr.stateAfter().toString(Verbosity.Debugger)); } return osr; } + private static LoopBeginNode osrLoop(EntryMarkerNode osr) { + // Check that there is an OSR loop for the OSR begin + LoopsData loops = new LoopsData(osr.graph()); + Loop l = loops.getCFG().getNodeToBlock().get(osr).getLoop(); + if (l == null) { + return null; + } + return (LoopBeginNode) l.getHeader().getBeginNode(); + } + + private static boolean osrWithLocks(EntryMarkerNode osr) { + return osr.stateAfter().locksSize() != 0; + } + @Override public float codeSizeIncrease() { return 5.0f; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java index a252994fe7b..f837b9127e6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java @@ -35,8 +35,8 @@ import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ArrayRangeWriteNode; +import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode; import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode; -import org.graalvm.compiler.nodes.java.LoweredCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.FixedAccessNode; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; import org.graalvm.compiler.nodes.memory.ReadNode; @@ -63,8 +63,8 @@ public class WriteBarrierAdditionPhase extends Phase { } else if (n instanceof LoweredAtomicReadAndWriteNode) { LoweredAtomicReadAndWriteNode loweredAtomicReadAndWriteNode = (LoweredAtomicReadAndWriteNode) n; addAtomicReadWriteNodeBarriers(loweredAtomicReadAndWriteNode, graph); - } else if (n instanceof LoweredCompareAndSwapNode) { - addCASBarriers((LoweredCompareAndSwapNode) n, graph); + } else if (n instanceof AbstractCompareAndSwapNode) { + addCASBarriers((AbstractCompareAndSwapNode) n, graph); } else if (n instanceof ArrayRangeWriteNode) { ArrayRangeWriteNode node = (ArrayRangeWriteNode) n; if (node.isObjectArray()) { @@ -116,7 +116,7 @@ public class WriteBarrierAdditionPhase extends Phase { case PRECISE: boolean precise = barrierType == BarrierType.PRECISE; if (config.useG1GC) { - if (!node.isInitialization()) { + if (!node.getLocationIdentity().isInit()) { addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph); } addG1PostWriteBarrier(node, node.getAddress(), node.value(), precise, graph); @@ -150,7 +150,7 @@ public class WriteBarrierAdditionPhase extends Phase { } } - private void addCASBarriers(LoweredCompareAndSwapNode node, StructuredGraph graph) { + private void addCASBarriers(AbstractCompareAndSwapNode node, StructuredGraph graph) { BarrierType barrierType = node.getBarrierType(); switch (barrierType) { case NONE: diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java index 1cd9421ffe6..639292f3772 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierVerificationPhase.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.hotspot.nodes.ArrayRangeWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.ObjectWriteBarrier; import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; +import org.graalvm.compiler.nodeinfo.Verbosity; import org.graalvm.compiler.nodes.DeoptimizingNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.LoopBeginNode; @@ -40,7 +41,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ArrayRangeWriteNode; import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode; -import org.graalvm.compiler.nodes.java.LoweredCompareAndSwapNode; +import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode; import org.graalvm.compiler.nodes.memory.FixedAccessNode; import org.graalvm.compiler.nodes.memory.HeapAccess; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; @@ -48,6 +49,7 @@ import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.WriteNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.type.StampTool; +import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.phases.Phase; /** @@ -73,6 +75,12 @@ public class WriteBarrierVerificationPhase extends Phase { private void processWrites(StructuredGraph graph) { for (Node node : graph.getNodes()) { if (isObjectWrite(node) || isObjectArrayRangeWrite(node)) { + if (node instanceof WriteNode) { + WriteNode writeNode = (WriteNode) node; + if (StampTool.isPointerAlwaysNull(writeNode.value())) { + continue; + } + } validateWrite(node); } } @@ -92,7 +100,7 @@ public class WriteBarrierVerificationPhase extends Phase { while (iterator.hasNext()) { Node currentNode = iterator.next(); if (isSafepoint(currentNode)) { - throw new AssertionError("Write barrier must be present " + write); + throw new AssertionError("Write barrier must be present " + write.toString(Verbosity.All) + " / " + write.inputs()); } if (useG1GC()) { if (!(currentNode instanceof G1PostWriteBarrier) || (!validateBarrier((FixedAccessNode) write, (ObjectWriteBarrier) currentNode))) { @@ -114,7 +122,13 @@ public class WriteBarrierVerificationPhase extends Phase { private boolean hasAttachedBarrier(FixedWithNextNode node) { final Node next = node.next(); final Node previous = node.predecessor(); - final boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWriteNode) node).isInitialization()); + boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWriteNode) node).isInitialization()); + if (node instanceof WriteNode) { + WriteNode writeNode = (WriteNode) node; + if (writeNode.getLocationIdentity().isInit()) { + validatePreBarrier = false; + } + } if (isObjectWrite(node)) { return (isObjectBarrier(node, next) || StampTool.isPointerAlwaysNull(getValueWritten(node))) && (!validatePreBarrier || isObjectBarrier(node, previous)); } else if (isObjectArrayRangeWrite(node)) { @@ -150,6 +164,10 @@ public class WriteBarrierVerificationPhase extends Phase { } private static boolean isSafepoint(Node node) { + if (node instanceof FixedAccessNode) { + // Implicit null checks on reads or writes do not count. + return false; + } /* * LoopBegin nodes are also treated as safepoints since a bottom-up analysis is performed * and loop safepoints are placed before LoopEnd nodes. Possible elimination of write @@ -161,8 +179,8 @@ public class WriteBarrierVerificationPhase extends Phase { private static ValueNode getValueWritten(FixedWithNextNode write) { if (write instanceof WriteNode) { return ((WriteNode) write).value(); - } else if (write instanceof LoweredCompareAndSwapNode) { - return ((LoweredCompareAndSwapNode) write).getNewValue(); + } else if (write instanceof LogicCompareAndSwapNode) { + return ((LogicCompareAndSwapNode) write).getNewValue(); } else if (write instanceof LoweredAtomicReadAndWriteNode) { return ((LoweredAtomicReadAndWriteNode) write).getNewValue(); } else { @@ -171,10 +189,10 @@ public class WriteBarrierVerificationPhase extends Phase { } private static boolean validateBarrier(FixedAccessNode write, ObjectWriteBarrier barrier) { - assert write instanceof WriteNode || write instanceof LoweredCompareAndSwapNode || write instanceof LoweredAtomicReadAndWriteNode : "Node must be of type requiring a write barrier " + write; + assert write instanceof WriteNode || write instanceof LogicCompareAndSwapNode || write instanceof LoweredAtomicReadAndWriteNode : "Node must be of type requiring a write barrier " + write; if (!barrier.usePrecise()) { if (barrier.getAddress() instanceof OffsetAddressNode && write.getAddress() instanceof OffsetAddressNode) { - return ((OffsetAddressNode) barrier.getAddress()).getBase() == ((OffsetAddressNode) write.getAddress()).getBase(); + return GraphUtil.unproxify(((OffsetAddressNode) barrier.getAddress()).getBase()) == GraphUtil.unproxify(((OffsetAddressNode) write.getAddress()).getBase()); } } return barrier.getAddress() == write.getAddress(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java index 8f1efa35b38..55c0f35e87c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java @@ -27,12 +27,12 @@ import static org.graalvm.compiler.core.common.GraalOptions.TrivialInliningSize; import java.util.Map; -import org.graalvm.compiler.hotspot.FingerprintUtil; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.spi.Replacements; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.inlining.InliningUtil; import org.graalvm.compiler.phases.common.inlining.info.InlineInfo; import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy; @@ -44,11 +44,11 @@ public class AOTInliningPolicy extends GreedyInliningPolicy { public static class Options { // @formatter:off @Option(help = "", type = OptionType.Expert) - public static final OptionValue AOTInliningDepthToSizeRate = new OptionValue<>(2.5); + public static final OptionKey AOTInliningDepthToSizeRate = new OptionKey<>(2.5); @Option(help = "", type = OptionType.Expert) - public static final OptionValue AOTInliningSizeMaximum = new OptionValue<>(300); + public static final OptionKey AOTInliningSizeMaximum = new OptionKey<>(300); @Option(help = "", type = OptionType.Expert) - public static final OptionValue AOTInliningSizeMinimum = new OptionValue<>(50); + public static final OptionKey AOTInliningSizeMinimum = new OptionKey<>(50); // @formatter:on } @@ -56,8 +56,8 @@ public class AOTInliningPolicy extends GreedyInliningPolicy { super(hints); } - protected double maxInliningSize(int inliningDepth) { - return Math.max(Options.AOTInliningSizeMaximum.getValue() / (inliningDepth * Options.AOTInliningDepthToSizeRate.getValue()), Options.AOTInliningSizeMinimum.getValue()); + protected double maxInliningSize(int inliningDepth, OptionValues options) { + return Math.max(Options.AOTInliningSizeMaximum.getValue(options) / (inliningDepth * Options.AOTInliningDepthToSizeRate.getValue(options)), Options.AOTInliningSizeMinimum.getValue(options)); } @Override @@ -66,7 +66,7 @@ public class AOTInliningPolicy extends GreedyInliningPolicy { for (int i = 0; i < info.numberOfMethods(); ++i) { HotSpotResolvedObjectType t = (HotSpotResolvedObjectType) info.methodAt(i).getDeclaringClass(); - if (FingerprintUtil.getFingerprint(t) == 0) { + if (t.getFingerprint() == 0) { return false; } } @@ -74,7 +74,8 @@ public class AOTInliningPolicy extends GreedyInliningPolicy { final double probability = invocation.probability(); final double relevance = invocation.relevance(); - if (InlineEverything.getValue()) { + OptionValues options = info.graph().getOptions(); + if (InlineEverything.getValue(options)) { InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything"); return true; } @@ -92,12 +93,12 @@ public class AOTInliningPolicy extends GreedyInliningPolicy { double inliningBonus = getInliningBonus(info); int nodes = info.determineNodeCount(); - if (nodes < TrivialInliningSize.getValue() * inliningBonus) { + if (nodes < TrivialInliningSize.getValue(options) * inliningBonus) { InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes); return true; } - double maximumNodes = computeMaximumSize(relevance, (int) (maxInliningSize(inliningDepth) * inliningBonus)); + double maximumNodes = computeMaximumSize(relevance, (int) (maxInliningSize(inliningDepth, options) * inliningBonus)); if (nodes <= maximumNodes) { InliningUtil.logInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus, nodes, maximumNodes); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java index caa04c2c979..552c91a611f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -22,160 +22,31 @@ */ package org.graalvm.compiler.hotspot.phases.aot; -import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; +import static org.graalvm.util.CollectionsUtil.anyMatch; import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map.Entry; +import java.util.Iterator; +import java.util.List; import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; -import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; +import org.graalvm.compiler.nodes.AbstractMergeNode; +import org.graalvm.compiler.nodes.FixedNode; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.Invoke; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.cfg.Block; -import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.phases.BasePhase; +import org.graalvm.compiler.phases.graph.MergeableState; +import org.graalvm.compiler.phases.graph.PostOrderNodeIterator; import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ResolvedJavaType; public class EliminateRedundantInitializationPhase extends BasePhase { - /** - * Find blocks with class initializing nodes for the class identified the by the constant node. - * Return the map of a block to a list of initializing nodes in that block. - * - * @param cfg an instance of the {@link ControlFlowGraph}. - * @param constant common input to the instances of {@link InitializeKlassNode}. - * @return map of blocks to lists of initializing nodes. - */ - private static HashMap> findBlocksWithInitializers(ControlFlowGraph cfg, ConstantNode constant) { - // node is ConstantNode representing a metaspace constant (a klass reference). - // InitializeKlassNodes for the same class would share the same ConstantNode input. - NodeIterable initializers = constant.usages().filter(InitializeKlassNode.class); - // Map the found nodes to blocks - HashMap> blockToInits = new HashMap<>(); - for (Node i : initializers) { - Block b = cfg.blockFor(i); - ArrayList initsInBlock = blockToInits.get(b); - if (initsInBlock == null) { - initsInBlock = new ArrayList<>(); - } - initsInBlock.add(i); - blockToInits.put(b, initsInBlock); - } - return blockToInits; - } - - /** - * Process the block-to-initializers map and produce a list of blocks that contain more than one - * instance of {@link InitializeKlassNode}. - * - * @param blockToInits a map of blocks to lists of {@link InitializeKlassNode} instances. - * @return list of blocks that contain multiple instances of {@link InitializeKlassNode}. - */ - private static ArrayList findBlocksWithMultipleInitializers(HashMap> blockToInits) { - ArrayList result = new ArrayList<>(); - // Select the blocks from the blocksToInits map that have more than one InitializeKlassNode - for (Entry> e : blockToInits.entrySet()) { - if (e.getValue().size() > 1) { - result.add(e.getKey()); - } - } - return result; - } - - /** - * Iterate through blocks with multiple instances of {@link InitializeKlassNode} and identify - * redundant instances. Remove redundant instances from the block-to-list-of-initializer map. - * - * @param blockToInits a map of blocks to lists of {@link InitializeKlassNode} instances. - * @param blocksWithMultipleInits a list of blocks that contain multiple instances of - * {@link InitializeKlassNode}. - * @param constant common input to the instances of {@link InitializeKlassNode}. - * @return list of {@link InitializeKlassNode} instances that can be removed. - */ - private static ArrayList findRedundantLocalInitializers(HashMap> blockToInits, ArrayList blocksWithMultipleInits, ConstantNode constant) { - ArrayList result = new ArrayList<>(); - for (Block b : blocksWithMultipleInits) { - // First initializer for our constant in the block - InitializeKlassNode first = null; - for (Node n : b.getNodes()) { - if (n instanceof InitializeKlassNode) { - InitializeKlassNode i = (InitializeKlassNode) n; - if (i.value() == constant) { - if (first == null) { - // First instance of {@link InitializeKlassNode} stays. - first = i; - } else { - // All the following instances of {@link InitializeKlassNode} can be - // removed. - result.add(i); - } - } - } - } - assert first != null; - - // Replace the entry in the initsInBlock map to contain just a single initializer - ArrayList initsInBlock = new ArrayList<>(); - initsInBlock.add(first); - blockToInits.put(b, initsInBlock); - } - return result; - } - - /** - * Find cases when one {@link InitializeKlassNode} instance dominates another. The dominated - * instance can be removed. - * - * @param blockToInits a map of blocks to lists of {@link InitializeKlassNode} instances. - * @return list of {@link InitializeKlassNode} instances that can be removed. - */ - private static ArrayList findRedundantGlobalInitializers(HashMap> blockToInits) { - ArrayList result = new ArrayList<>(); - for (Entry> e : blockToInits.entrySet()) { - Block currentBlock = e.getKey(); - ArrayList nodesInCurrent = e.getValue(); - if (nodesInCurrent != null) { // if the list is null, the initializer has already been - // eliminated. - for (Block d : currentBlock.getDominated()) { - ArrayList nodesInDominated = blockToInits.get(d); - if (nodesInDominated != null) { // if the list is null, the initializer has - // already been eliminated. - assert nodesInDominated.size() == 1; - Node n = nodesInDominated.iterator().next(); - result.add(n); - blockToInits.put(d, null); - } - } - } - } - return result; - } - - /** - * Compute the list of redundant {@link InitializeKlassNode} instances that have the common - * {@link ConstantNode}. - * - * @param cfg an instance of the {@link ControlFlowGraph}. - * @param constant common input to the instances of {@link InitializeKlassNode}. - * @return list of {@link InitializeKlassNode} instances that can be removed. - */ - private static ArrayList processConstantNode(ControlFlowGraph cfg, ConstantNode constant) { - HashMap> blockToInits = findBlocksWithInitializers(cfg, constant); - ArrayList blocksWithMultipleInits = findBlocksWithMultipleInitializers(blockToInits); - ArrayList redundantInits = findRedundantLocalInitializers(blockToInits, blocksWithMultipleInits, constant); - // At this point each block has at most one initializer for this constant - if (blockToInits.size() > 1) { - redundantInits.addAll(findRedundantGlobalInitializers(blockToInits)); - } - return redundantInits; - } - /** * Find each {@link Invoke} that has a corresponding {@link InitializeKlassNode}. These * {@link InitializeKlassNode} are redundant and are removed. @@ -192,25 +63,191 @@ public class EliminateRedundantInitializationPhase extends BasePhase redundantInits = new ArrayList<>(); - for (ConstantNode node : getConstantNodes(graph)) { - Constant constant = node.asConstant(); - if (constant instanceof HotSpotMetaspaceConstant) { - redundantInits.addAll(processConstantNode(cfg, node)); + // Find and remove redundant nodes from the graph. + List redundantNodes = findRedundantInits(graph); + for (FixedWithNextNode n : redundantNodes) { + graph.removeFixed(n); + } + } + + /** + * Find {@link InitializeKlassNode} and {@link ResolveConstantNode} instances that can be + * removed because there is an existing dominating node. + * + * @param graph the program graph + */ + private static List findRedundantInits(StructuredGraph graph) { + EliminateRedundantInitializationIterator i = new EliminateRedundantInitializationIterator(graph.start(), new InitializedTypes()); + i.apply(); + return i.getRedundantNodes(); + } + + /** + * State for {@link EliminateRedundantInitializationIterator}. + */ + private static class InitializedTypes extends MergeableState implements Cloneable { + private EconomicSet types; + + InitializedTypes() { + types = EconomicSet.create(); + } + + private InitializedTypes(EconomicSet types) { + this.types = types; + } + + @Override + public InitializedTypes clone() { + return new InitializedTypes(EconomicSet.create(types)); + } + + public boolean contains(ResolvedJavaType type) { + if (type.isInterface() || type.isArray()) { + // Check for exact match for interfaces + return types.contains(type); + } + // For other types see if there is the same type or a subtype + return anyMatch(types, t -> type.isAssignableFrom(t)); + } + + public void add(ResolvedJavaType type) { + types.add(type); + } + + /** + * Merge two given types. Interfaces and arrays have to be the same to merge successfully. + * For other types the answer is the LCA. + * + * @param a initialized type + * @param b initialized type + * @return lowest common type that is initialized if either a or b are initialized, null if + * no such type exists. + */ + private static ResolvedJavaType merge(ResolvedJavaType a, ResolvedJavaType b) { + // We want exact match for interfaces or arrays + if (a.isInterface() || b.isInterface() || a.isArray() || b.isArray()) { + if (a.equals(b)) { + return a; + } else { + return null; + } + } else { + // And LCA for other types + ResolvedJavaType c = a.findLeastCommonAncestor(b); + if (c.isJavaLangObject()) { + // Not a very useful type, always initialized, don't pollute the sets. + return null; + } + return c; } } - // Remove redundant instances of {@link InitializeKlassNode} from the graph. - for (Node n : redundantInits) { - graph.removeFixed((FixedWithNextNode) n); + + /** + * Merge two sets of types. Essentially a computation of the LCA for each element of the + * cartesian product of the input sets. Interfaces have to match exactly. + * + * @param a set of initialized types + * @param b set of initialized types + * @return set of common types that would be initialized if types in either a or b are + * initialized + */ + private static EconomicSet merge(EconomicSet a, EconomicSet b) { + EconomicSet c = EconomicSet.create(); + for (ResolvedJavaType ta : a) { + for (ResolvedJavaType tb : b) { + ResolvedJavaType tc = merge(ta, tb); + if (tc != null) { + c.add(tc); + if (tc.isInterface() || tc.isArray()) { + // Interfaces and arrays are not going merge with anything else, so bail + // out early. + break; + } + } + } + } + return c; } + + @Override + public boolean merge(AbstractMergeNode merge, List withStates) { + for (InitializedTypes ts : withStates) { + types = merge(types, ts.types); + } + return true; + } + + protected static String toString(EconomicSet types) { + StringBuilder b = new StringBuilder(); + b.append("["); + Iterator i = types.iterator(); + while (i.hasNext()) { + ResolvedJavaType t = i.next(); + b.append(t.toString()); + if (i.hasNext()) { + b.append(","); + } + } + b.append("]"); + return b.toString(); + } + + @Override + public String toString() { + return toString(types); + } + } + + /** + * Do data flow analysis of class initializations and array resolutions. Collect redundant + * nodes. + */ + private static class EliminateRedundantInitializationIterator extends PostOrderNodeIterator { + private List redundantNodes = new ArrayList<>(); + + public List getRedundantNodes() { + return redundantNodes; + } + + EliminateRedundantInitializationIterator(FixedNode start, InitializedTypes initialState) { + super(start, initialState); + } + + private void processType(FixedWithNextNode node, Constant c) { + HotSpotMetaspaceConstant klass = (HotSpotMetaspaceConstant) c; + ResolvedJavaType t = klass.asResolvedJavaType(); + if (t != null) { + if (state.contains(t)) { + redundantNodes.add(node); + } else { + state.add(t); + } + } + } + + @Override + protected void node(FixedNode node) { + if (node instanceof InitializeKlassNode) { + InitializeKlassNode i = (InitializeKlassNode) node; + if (i.value().isConstant()) { + processType(i, i.value().asConstant()); + } + } else if (node instanceof ResolveConstantNode) { + ResolveConstantNode r = (ResolveConstantNode) node; + if (r.hasNoUsages()) { + if (r.value().isConstant()) { + processType(r, r.value().asConstant()); + } + } + } + } + } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java index 2766877c02a..186dcabe550 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2017, 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 @@ -22,11 +22,50 @@ */ package org.graalvm.compiler.hotspot.phases.aot; +import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.strictlyDominates; import static org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode.getLoadMethodCountersNodes; import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes; import java.util.HashSet; +import java.util.List; +import org.graalvm.compiler.core.common.cfg.BlockMap; +import org.graalvm.compiler.core.common.type.ObjectStamp; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.graph.Node; +import org.graalvm.compiler.graph.NodeMap; +import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; +import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; +import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyFixedNode; +import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; +import org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode; +import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; +import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; +import org.graalvm.compiler.nodes.AbstractBeginNode; +import org.graalvm.compiler.nodes.AbstractMergeNode; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.FixedNode; +import org.graalvm.compiler.nodes.FixedWithNextNode; +import org.graalvm.compiler.nodes.FrameState; +import org.graalvm.compiler.nodes.LoopBeginNode; +import org.graalvm.compiler.nodes.LoopExitNode; +import org.graalvm.compiler.nodes.StateSplit; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.FloatingNode; +import org.graalvm.compiler.nodes.cfg.Block; +import org.graalvm.compiler.phases.BasePhase; +import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; +import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; +import org.graalvm.compiler.phases.schedule.SchedulePhase; +import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy; +import org.graalvm.compiler.phases.tiers.PhaseContext; +import org.graalvm.util.EconomicMap; + +import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; @@ -35,28 +74,10 @@ import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.ResolvedJavaType; -import org.graalvm.compiler.core.common.type.ObjectStamp; -import org.graalvm.compiler.core.common.type.Stamp; -import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node; -import org.graalvm.compiler.hotspot.FingerprintUtil; -import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; -import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode; -import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyFixedNode; -import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; -import org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode; -import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.phases.BasePhase; -import org.graalvm.compiler.phases.tiers.PhaseContext; - public class ReplaceConstantNodesPhase extends BasePhase { private static final HashSet> builtIns = new HashSet<>(); + private final boolean verifyFingerprints; static { builtIns.add(Boolean.class); @@ -91,90 +112,388 @@ public class ReplaceConstantNodesPhase extends BasePhase { // @formatter:on } + private static boolean anyUsagesNeedReplacement(ConstantNode node) { + return node.usages().filter(n -> !isReplacementNode(n)).isNotEmpty(); + } + + private static boolean anyUsagesNeedReplacement(LoadMethodCountersNode node) { + return node.usages().filter(n -> !(n instanceof ResolveMethodAndLoadCountersNode)).isNotEmpty(); + } + private static boolean checkForBadFingerprint(HotSpotResolvedJavaType type) { if (type.isArray()) { if (type.getElementalType().isPrimitive()) { return false; } - return FingerprintUtil.getFingerprint((HotSpotResolvedObjectType) (type.getElementalType())) == 0; + return ((HotSpotResolvedObjectType) (type.getElementalType())).getFingerprint() == 0; } - return FingerprintUtil.getFingerprint((HotSpotResolvedObjectType) type) == 0; + return ((HotSpotResolvedObjectType) type).getFingerprint() == 0; } - private static void handleHotSpotMetaspaceConstant(StructuredGraph graph, ConstantNode node) { + /** + * Insert the replacement node into the graph. We may need to insert it into a place different + * than the original {@link FloatingNode} since we need to make sure that replacement will have + * a valid state assigned. + * + * @param graph + * @param stateMapper + * @param node + * @param replacement + */ + private static void insertReplacement(StructuredGraph graph, FrameStateMapperClosure stateMapper, FloatingNode node, FixedWithNextNode replacement) { + FixedWithNextNode insertionPoint = findInsertionPoint(graph, stateMapper, node); + graph.addAfterFixed(insertionPoint, replacement); + stateMapper.addState(replacement, stateMapper.getState(insertionPoint)); + } + + /** + * Find a good place to insert a stateful fixed node that is above the given node. A good + * insertion point should have a valid FrameState reaching it. + * + * @param graph + * @param stateMapper + * @param node start search from this node up + * @return an insertion point + */ + private static FixedWithNextNode findInsertionPoint(StructuredGraph graph, FrameStateMapperClosure stateMapper, FloatingNode node) { + FixedWithNextNode fixed = findFixedBeforeFloating(graph, node); + FixedWithNextNode result = findFixedWithValidState(graph, stateMapper, fixed); + return result; + } + + /** + * Find the first {@link FixedWithNextNode} that is currently scheduled before the given + * floating node. + * + * @param graph + * @param node start search from this node up + * @return the first {@link FixedWithNextNode} + */ + private static FixedWithNextNode findFixedBeforeFloating(StructuredGraph graph, FloatingNode node) { + ScheduleResult schedule = graph.getLastSchedule(); + NodeMap nodeToBlock = schedule.getNodeToBlockMap(); + Block block = nodeToBlock.get(node); + BlockMap> blockToNodes = schedule.getBlockToNodesMap(); + FixedWithNextNode result = null; + for (Node n : blockToNodes.get(block)) { + if (n.equals(node)) { + break; + } + if (n instanceof FixedWithNextNode) { + result = (FixedWithNextNode) n; + } + } + assert result != null; + return result; + } + + /** + * Find first dominating {@link FixedWithNextNode} that has a valid state reaching it starting + * from the given node. + * + * @param graph + * @param stateMapper + * @param node + * @return {@link FixedWithNextNode} that we can use as an insertion point + */ + private static FixedWithNextNode findFixedWithValidState(StructuredGraph graph, FrameStateMapperClosure stateMapper, FixedWithNextNode node) { + ScheduleResult schedule = graph.getLastSchedule(); + NodeMap nodeToBlock = schedule.getNodeToBlockMap(); + Block block = nodeToBlock.get(node); + + Node n = node; + do { + if (isFixedWithValidState(stateMapper, n)) { + return (FixedWithNextNode) n; + } + while (n != block.getBeginNode()) { + n = n.predecessor(); + if (isFixedWithValidState(stateMapper, n)) { + return (FixedWithNextNode) n; + } + } + block = block.getDominator(); + if (block != null) { + n = block.getEndNode(); + } + } while (block != null); + + return graph.start(); + } + + private static boolean isFixedWithValidState(FrameStateMapperClosure stateMapper, Node n) { + if (n instanceof FixedWithNextNode) { + FixedWithNextNode fixed = (FixedWithNextNode) n; + assert stateMapper.getState(fixed) != null; + if (!BytecodeFrame.isPlaceholderBci(stateMapper.getState(fixed).bci)) { + return true; + } + } + return false; + } + + /** + * Compute frame states for all fixed nodes in the graph. + */ + private static class FrameStateMapperClosure extends NodeIteratorClosure { + private NodeMap reachingStates; + + @Override + protected FrameState processNode(FixedNode node, FrameState previousState) { + FrameState currentState = previousState; + if (node instanceof StateSplit) { + StateSplit stateSplit = (StateSplit) node; + FrameState stateAfter = stateSplit.stateAfter(); + if (stateAfter != null) { + currentState = stateAfter; + } + } + reachingStates.put(node, currentState); + return currentState; + } + + @Override + protected FrameState merge(AbstractMergeNode merge, List states) { + FrameState singleFrameState = singleFrameState(states); + FrameState currentState = singleFrameState == null ? merge.stateAfter() : singleFrameState; + reachingStates.put(merge, currentState); + return currentState; + } + + @Override + protected FrameState afterSplit(AbstractBeginNode node, FrameState oldState) { + return oldState; + } + + @Override + protected EconomicMap processLoop(LoopBeginNode loop, FrameState initialState) { + return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates; + } + + private static FrameState singleFrameState(List states) { + FrameState singleState = states.get(0); + for (int i = 1; i < states.size(); ++i) { + if (states.get(i) != singleState) { + return null; + } + } + return singleState; + } + + FrameStateMapperClosure(StructuredGraph graph) { + reachingStates = new NodeMap<>(graph); + } + + public FrameState getState(Node n) { + return reachingStates.get(n); + } + + public void addState(Node n, FrameState s) { + reachingStates.setAndGrow(n, s); + } + } + + /** + * Try to find dominating node doing the resolution that can be reused. + * + * @param graph + * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs + * resolution. + */ + private static void tryToReplaceWithExisting(StructuredGraph graph, ConstantNode node) { + ScheduleResult schedule = graph.getLastSchedule(); + NodeMap nodeToBlock = schedule.getNodeToBlockMap(); + BlockMap> blockToNodes = schedule.getBlockToNodesMap(); + + EconomicMap blockToExisting = EconomicMap.create(); + for (Node n : node.usages().filter(n -> isReplacementNode(n))) { + blockToExisting.put(nodeToBlock.get(n), n); + } + for (Node use : node.usages().filter(n -> !isReplacementNode(n)).snapshot()) { + boolean replaced = false; + Block b = nodeToBlock.get(use); + Node e = blockToExisting.get(b); + if (e != null) { + // There is an initialization or resolution in the same block as the use, look if + // the use is scheduled after it. + for (Node n : blockToNodes.get(b)) { + if (n.equals(use)) { + // Usage is before initialization, can't use it + break; + } + if (n.equals(e)) { + use.replaceFirstInput(node, e); + replaced = true; + break; + } + } + } + if (!replaced) { + // Look for dominating blocks that have existing nodes + for (Block d : blockToExisting.getKeys()) { + if (strictlyDominates(d, b)) { + use.replaceFirstInput(node, blockToExisting.get(d)); + break; + } + } + } + } + } + + /** + * Replace the uses of a constant with either {@link LoadConstantIndirectlyNode} or + * {@link ResolveConstantNode}. + * + * @param graph + * @param stateMapper + * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs + * resolution. + */ + private static void replaceWithResolution(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node) { + HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant(); + HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType(); + ResolvedJavaType topMethodHolder = graph.method().getDeclaringClass(); + ValueNode replacement; + + if (type.isArray() && type.getComponentType().isPrimitive()) { + // Special case for primitive arrays. The AOT runtime pre-resolves them, so we may + // omit the resolution call. + replacement = graph.addOrUnique(new LoadConstantIndirectlyNode(node)); + } else if (type.equals(topMethodHolder) || (type.isAssignableFrom(topMethodHolder) && !type.isInterface())) { + // If it's a supertype of or the same class that declares the top method, we are + // guaranteed to have it resolved already. If it's an interface, we just test for + // equality. + replacement = graph.addOrUnique(new LoadConstantIndirectlyNode(node)); + } else { + FixedWithNextNode fixedReplacement; + if (builtIns.contains(type.mirror())) { + // Special case of klass constants that come from {@link BoxingSnippets}. + fixedReplacement = graph.add(new ResolveConstantNode(node, HotSpotConstantLoadAction.INITIALIZE)); + } else { + fixedReplacement = graph.add(new ResolveConstantNode(node)); + } + insertReplacement(graph, stateMapper, node, fixedReplacement); + replacement = fixedReplacement; + } + node.replaceAtUsages(replacement, n -> !isReplacementNode(n)); + } + + /** + * Replace {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} with indirection. + * + * @param graph + * @param stateMapper + * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs + * resolution. + */ + private void handleHotSpotMetaspaceConstant(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node) { HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant(); HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType(); if (type != null) { - if (checkForBadFingerprint(type)) { + if (verifyFingerprints && checkForBadFingerprint(type)) { throw new GraalError("Type with bad fingerprint: " + type); } - assert !metaspaceConstant.isCompressed() : "No support for replacing compressed metaspace constants"; - ResolvedJavaType topMethodHolder = graph.method().getDeclaringClass(); - ValueNode replacement; - - if (type.isArray() && type.getComponentType().isPrimitive()) { - // Special case for primitive arrays. The AOT runtime pre-resolves them, so we may - // omit the resolution call. - replacement = new LoadConstantIndirectlyNode(node); - } else if (type.equals(topMethodHolder) || (type.isAssignableFrom(topMethodHolder) && !type.isInterface())) { - // If it's a supertype of or the same class that declares the top method, we are - // guaranteed to have it resolved already. If it's an interface, we just test for - // equality. - replacement = new LoadConstantIndirectlyNode(node); - } else if (builtIns.contains(type.mirror())) { - // Special case of klass constants that come from {@link BoxingSnippets}. - replacement = new ResolveConstantNode(node, HotSpotConstantLoadAction.INITIALIZE); - } else { - replacement = new ResolveConstantNode(node); + tryToReplaceWithExisting(graph, node); + if (anyUsagesNeedReplacement(node)) { + replaceWithResolution(graph, stateMapper, node); } - - node.replaceAtUsages(graph.addOrUnique(replacement), n -> !isReplacementNode(n)); } else { throw new GraalError("Unsupported metaspace constant type: " + type); } } - private static void handleHotSpotObjectConstant(StructuredGraph graph, ConstantNode node) { + /** + * Replace an object constant with an indirect load {@link ResolveConstantNode}. Currently we + * support only strings. + * + * @param graph + * @param stateMapper + * @param node {@link ConstantNode} containing a {@link HotSpotObjectConstant} that needs + * resolution. + */ + private static void handleHotSpotObjectConstant(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node) { HotSpotObjectConstant constant = (HotSpotObjectConstant) node.asJavaConstant(); HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) constant.getType(); if (type.mirror().equals(String.class)) { assert !constant.isCompressed() : "No support for replacing compressed oop constants"; - ValueNode replacement = graph.unique(new ResolveConstantNode(node)); + FixedWithNextNode replacement = graph.add(new ResolveConstantNode(node)); + insertReplacement(graph, stateMapper, node, replacement); node.replaceAtUsages(replacement, n -> !(n instanceof ResolveConstantNode)); } else { throw new GraalError("Unsupported object constant type: " + type); } } - private static void handleLoadMethodCounters(StructuredGraph graph, LoadMethodCountersNode node, PhaseContext context) { + /** + * Replace {@link LoadMethodCountersNode} with indirect load + * {@link ResolveMethodAndLoadCountersNode}, expose a klass constant of the holder. + * + * @param graph + * @param stateMapper + * @param node + * @param context + */ + private static void handleLoadMethodCounters(StructuredGraph graph, FrameStateMapperClosure stateMapper, LoadMethodCountersNode node, PhaseContext context) { ResolvedJavaType type = node.getMethod().getDeclaringClass(); Stamp hubStamp = context.getStampProvider().createHubStamp((ObjectStamp) StampFactory.objectNonNull()); ConstantReflectionProvider constantReflection = context.getConstantReflection(); ConstantNode klassHint = ConstantNode.forConstant(hubStamp, constantReflection.asObjectHub(type), context.getMetaAccess(), graph); - ValueNode replacement = graph.unique(new ResolveMethodAndLoadCountersNode(node.getMethod(), klassHint)); + FixedWithNextNode replacement = graph.add(new ResolveMethodAndLoadCountersNode(node.getMethod(), klassHint)); + insertReplacement(graph, stateMapper, node, replacement); node.replaceAtUsages(replacement, n -> !(n instanceof ResolveMethodAndLoadCountersNode)); } + /** + * Replace {@link LoadMethodCountersNode} with {@link ResolveMethodAndLoadCountersNode}, expose + * klass constants. + * + * @param graph + * @param stateMapper + * @param context + */ + private static void replaceLoadMethodCounters(StructuredGraph graph, FrameStateMapperClosure stateMapper, PhaseContext context) { + new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false); + + for (LoadMethodCountersNode node : getLoadMethodCountersNodes(graph)) { + if (anyUsagesNeedReplacement(node)) { + handleLoadMethodCounters(graph, stateMapper, node, context); + } + } + } + + /** + * Replace object and klass constants with resolution nodes or reuse preceding initializations. + * + * @param graph + * @param stateMapper + */ + private void replaceKlassesAndObjects(StructuredGraph graph, FrameStateMapperClosure stateMapper) { + new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false); + + for (ConstantNode node : getConstantNodes(graph)) { + Constant constant = node.asConstant(); + if (constant instanceof HotSpotMetaspaceConstant && anyUsagesNeedReplacement(node)) { + handleHotSpotMetaspaceConstant(graph, stateMapper, node); + } else if (constant instanceof HotSpotObjectConstant && anyUsagesNeedReplacement(node)) { + handleHotSpotObjectConstant(graph, stateMapper, node); + } + } + } + @Override protected void run(StructuredGraph graph, PhaseContext context) { + FrameStateMapperClosure stateMapper = new FrameStateMapperClosure(graph); + ReentrantNodeIterator.apply(stateMapper, graph.start(), null); + // Replace LoadMethodCountersNode with ResolveMethodAndLoadCountersNode, expose klass // constants. - for (LoadMethodCountersNode node : getLoadMethodCountersNodes(graph)) { - handleLoadMethodCounters(graph, node, context); - } + replaceLoadMethodCounters(graph, stateMapper, context); // Replace object and klass constants (including the ones added in the previous pass) with // resolution nodes. - for (ConstantNode node : getConstantNodes(graph)) { - Constant constant = node.asConstant(); - if (constant instanceof HotSpotMetaspaceConstant) { - handleHotSpotMetaspaceConstant(graph, node); - } else if (constant instanceof HotSpotObjectConstant) { - handleHotSpotObjectConstant(graph, node); - } - } + replaceKlassesAndObjects(graph, stateMapper); } @Override @@ -182,4 +501,11 @@ public class ReplaceConstantNodesPhase extends BasePhase { return false; } + public ReplaceConstantNodesPhase() { + this(true); + } + + public ReplaceConstantNodesPhase(boolean verifyFingerprints) { + this.verifyFingerprints = verifyFingerprints; + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java index e0fe3c71713..07576103017 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/profiling/FinalizeProfileNodesPhase.java @@ -36,17 +36,17 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.LoopBeginNode; import org.graalvm.compiler.nodes.PhiNode; -import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.ValuePhiNode; import org.graalvm.compiler.nodes.calc.AddNode; import org.graalvm.compiler.nodes.calc.MulNode; import org.graalvm.compiler.nodes.cfg.Block; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.nodes.util.GraphUtil; import org.graalvm.compiler.options.Option; +import org.graalvm.compiler.options.OptionKey; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.tiers.PhaseContext; @@ -57,13 +57,13 @@ public class FinalizeProfileNodesPhase extends BasePhase { public static class Options { @Option(help = "Profile simple methods", type = OptionType.Expert)// - public static final OptionValue ProfileSimpleMethods = new OptionValue<>(true); + public static final OptionKey ProfileSimpleMethods = new OptionKey<>(true); @Option(help = "Maximum number of nodes in a graph for a simple method", type = OptionType.Expert)// - public static final OptionValue SimpleMethodGraphSize = new OptionValue<>(256); + public static final OptionKey SimpleMethodGraphSize = new OptionKey<>(256); @Option(help = "Maximum number of calls in a simple method", type = OptionType.Expert)// - public static final OptionValue SimpleMethodCalls = new OptionValue<>(1); + public static final OptionKey SimpleMethodCalls = new OptionKey<>(1); @Option(help = "Maximum number of indirect calls in a simple moethod", type = OptionType.Expert)// - public static final OptionValue SimpleMethodIndirectCalls = new OptionValue<>(0); + public static final OptionKey SimpleMethodIndirectCalls = new OptionKey<>(0); } @@ -88,12 +88,12 @@ public class FinalizeProfileNodesPhase extends BasePhase { // Hacky heuristic to determine whether we want any profiling in this method. // The heuristic is applied after the graph is fully formed and before the first lowering. private static boolean simpleMethodHeuristic(StructuredGraph graph) { - if (Options.ProfileSimpleMethods.getValue()) { + if (Options.ProfileSimpleMethods.getValue(graph.getOptions())) { return false; } // Check if the graph is smallish.. - if (graph.getNodeCount() > Options.SimpleMethodGraphSize.getValue()) { + if (graph.getNodeCount() > Options.SimpleMethodGraphSize.getValue(graph.getOptions())) { return false; } @@ -103,7 +103,7 @@ public class FinalizeProfileNodesPhase extends BasePhase { } // Check if method has calls - if (graph.getNodes().filter(InvokeNode.class).count() > Options.SimpleMethodCalls.getValue()) { + if (graph.getNodes().filter(InvokeNode.class).count() > Options.SimpleMethodCalls.getValue(graph.getOptions())) { return false; } @@ -160,7 +160,7 @@ public class FinalizeProfileNodesPhase extends BasePhase { } assignInlineeInvokeFrequencies(graph); - if (ProfileNode.Options.ProbabilisticProfiling.getValue()) { + if (ProfileNode.Options.ProbabilisticProfiling.getValue(graph.getOptions())) { assignRandomSources(graph); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java index 2240b335ed3..e525e6c7942 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java @@ -22,16 +22,15 @@ */ package org.graalvm.compiler.hotspot.replacements; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK; import static org.graalvm.compiler.hotspot.HotSpotBackend.DECRYPT_BLOCK_WITH_ORIGINAL_KEY; import static org.graalvm.compiler.hotspot.HotSpotBackend.ENCRYPT_BLOCK; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; @@ -40,9 +39,11 @@ import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; -import org.graalvm.compiler.word.Pointer; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.word.Word; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.Pointer; +import org.graalvm.word.WordFactory; import jdk.vm.ci.meta.DeoptimizationAction; import jdk.vm.ci.meta.DeoptimizationReason; @@ -59,7 +60,12 @@ public class AESCryptSubstitutions { static final long kOffset; static final long lastKeyOffset; static final Class AESCryptClass; - static final int AES_BLOCK_SIZE_IN_BYTES; + + /** + * The AES block size is a constant 128 bits as defined by the + * standard. + */ + static final int AES_BLOCK_SIZE_IN_BYTES = 16; static { try { @@ -70,9 +76,6 @@ public class AESCryptSubstitutions { AESCryptClass = Class.forName("com.sun.crypto.provider.AESCrypt", true, cl); kOffset = UnsafeAccess.UNSAFE.objectFieldOffset(AESCryptClass.getDeclaredField("K")); lastKeyOffset = UnsafeAccess.UNSAFE.objectFieldOffset(AESCryptClass.getDeclaredField("lastKey")); - // Thankfully the AES block size is a constant (128 bits) and so we don't need to - // reflect on com.sun.crypto.provider.AESConstants.AES_BLOCK_SIZE. - AES_BLOCK_SIZE_IN_BYTES = 16; } catch (Exception ex) { throw new GraalError(ex); } @@ -118,15 +121,15 @@ public class AESCryptSubstitutions { private static void crypt(Object rcvr, byte[] in, int inOffset, byte[] out, int outOffset, boolean encrypt, boolean withOriginalKey) { checkArgs(in, inOffset, out, outOffset); Object realReceiver = PiNode.piCastNonNull(rcvr, AESCryptClass); - Object kObject = UnsafeLoadNode.load(realReceiver, kOffset, JavaKind.Object, LocationIdentity.any()); + Object kObject = RawLoadNode.load(realReceiver, kOffset, JavaKind.Object, LocationIdentity.any()); Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(JavaKind.Int)); - Word inAddr = Word.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(JavaKind.Byte) + inOffset)); - Word outAddr = Word.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(JavaKind.Byte) + outOffset)); + Word inAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(JavaKind.Byte) + inOffset)); + Word outAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(JavaKind.Byte) + outOffset)); if (encrypt) { encryptBlockStub(ENCRYPT_BLOCK, inAddr, outAddr, kAddr); } else { if (withOriginalKey) { - Object lastKeyObject = UnsafeLoadNode.load(realReceiver, lastKeyOffset, JavaKind.Object, LocationIdentity.any()); + Object lastKeyObject = RawLoadNode.load(realReceiver, lastKeyOffset, JavaKind.Object, LocationIdentity.any()); Pointer lastKeyAddr = Word.objectToTrackedPointer(lastKeyObject).add(getArrayBaseOffset(JavaKind.Byte)); decryptBlockWithOriginalKeyStub(DECRYPT_BLOCK_WITH_ORIGINAL_KEY, inAddr, outAddr, kAddr, lastKeyAddr); } else { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java index a99dbd4c535..b2f87bbc0aa 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AssertionSnippets.java @@ -28,6 +28,7 @@ import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -35,6 +36,7 @@ import org.graalvm.compiler.hotspot.nodes.StubStartNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; @@ -53,15 +55,15 @@ public class AssertionSnippets implements Snippets { public static final ForeignCallDescriptor ASSERTION_VM_MESSAGE_C = new ForeignCallDescriptor("assertionVmMessageC", void.class, boolean.class, Word.class, long.class, long.class, long.class); @Snippet - public static void assertion(boolean value, @ConstantParameter String message) { - if (!value) { + public static void assertion(boolean condition, @ConstantParameter String message) { + if (!condition) { vmMessageC(ASSERTION_VM_MESSAGE_C, true, cstring(message), 0L, 0L, 0L); } } @Snippet - public static void stubAssertion(boolean value, @ConstantParameter String message) { - if (!value) { + public static void stubAssertion(boolean condition, @ConstantParameter String message) { + if (!condition) { vmMessageC(ASSERTION_VM_MESSAGE_C, true, cstring(message), 0L, 0L, 0L); } } @@ -74,17 +76,17 @@ public class AssertionSnippets implements Snippets { private final SnippetInfo assertion = snippet(AssertionSnippets.class, "assertion"); private final SnippetInfo stubAssertion = snippet(AssertionSnippets.class, "stubAssertion"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); } public void lower(AssertionNode assertionNode, LoweringTool tool) { StructuredGraph graph = assertionNode.graph(); Arguments args = new Arguments(graph.start() instanceof StubStartNode ? stubAssertion : assertion, graph.getGuardsStage(), tool.getLoweringStage()); - args.add("value", assertionNode.value()); + args.add("condition", assertionNode.condition()); args.addConst("message", "failed runtime assertion in snippet/stub: " + assertionNode.message() + " (" + graph.method() + ")"); - template(args).instantiate(providers.getMetaAccess(), assertionNode, DEFAULT_REPLACER, args); + template(assertionNode.getDebug(), args).instantiate(providers.getMetaAccess(), assertionNode, DEFAULT_REPLACER, args); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java index 1c1447d913a..8c8345e54aa 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java @@ -38,6 +38,9 @@ import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.word.Word; +import org.graalvm.word.Pointer; +import org.graalvm.word.WordBase; +import org.graalvm.word.WordFactory; import jdk.vm.ci.meta.JavaKind; @@ -57,21 +60,27 @@ public class CRC32Substitutions { return config.crcTableAddress; } + /** + * Removed in 9. + */ @MethodSubstitution(optional = true) static int update(int crc, int b) { - final long crcTableRawAddress = GraalHotSpotVMConfigNode.crcTableAddress(); + final Pointer crcTableRawAddress = WordFactory.pointer(GraalHotSpotVMConfigNode.crcTableAddress()); int c = ~crc; int index = (b ^ c) & 0xFF; int offset = index << 2; - int result = Word.unsigned(crcTableRawAddress).readInt(offset); + int result = crcTableRawAddress.readInt(offset); result = result ^ (c >>> 8); return ~result; } + /** + * Removed in 9. + */ @MethodSubstitution(optional = true) static int updateBytes(int crc, byte[] buf, int off, int len) { - Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, arrayBaseOffset(JavaKind.Byte) + off)); + Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, arrayBaseOffset(JavaKind.Byte) + off)); return updateBytesCRC32(UPDATE_BYTES_CRC32, crc, bufAddr, len); } @@ -80,13 +89,16 @@ public class CRC32Substitutions { */ @MethodSubstitution(optional = true) static int updateBytes0(int crc, byte[] buf, int off, int len) { - Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, arrayBaseOffset(JavaKind.Byte) + off)); + Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, arrayBaseOffset(JavaKind.Byte) + off)); return updateBytesCRC32(UPDATE_BYTES_CRC32, crc, bufAddr, len); } + /** + * Removed in 9. + */ @MethodSubstitution(optional = true) static int updateByteBuffer(int crc, long addr, int off, int len) { - Word bufAddr = Word.unsigned(addr).add(off); + WordBase bufAddr = WordFactory.unsigned(addr).add(off); return updateBytesCRC32(UPDATE_BYTES_CRC32, crc, bufAddr, len); } @@ -95,12 +107,12 @@ public class CRC32Substitutions { */ @MethodSubstitution(optional = true) static int updateByteBuffer0(int crc, long addr, int off, int len) { - Word bufAddr = Word.unsigned(addr).add(off); + WordBase bufAddr = WordFactory.unsigned(addr).add(off); return updateBytesCRC32(UPDATE_BYTES_CRC32, crc, bufAddr, len); } - public static final ForeignCallDescriptor UPDATE_BYTES_CRC32 = new ForeignCallDescriptor("updateBytesCRC32", int.class, int.class, Word.class, int.class); + public static final ForeignCallDescriptor UPDATE_BYTES_CRC32 = new ForeignCallDescriptor("updateBytesCRC32", int.class, int.class, WordBase.class, int.class); @NodeIntrinsic(ForeignCallNode.class) - public static native int updateBytesCRC32(@ConstantNodeParameter ForeignCallDescriptor descriptor, int crc, Word buf, int length); + public static native int updateBytesCRC32(@ConstantNodeParameter ForeignCallDescriptor descriptor, int crc, WordBase buf, int length); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java index ab52ce28373..7e6d2960d70 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java @@ -31,7 +31,6 @@ import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; @@ -39,9 +38,11 @@ import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; -import org.graalvm.compiler.word.Pointer; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.word.Word; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.Pointer; +import org.graalvm.word.WordFactory; import jdk.vm.ci.meta.JavaKind; @@ -82,7 +83,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false) static int encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false); @@ -95,7 +96,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false, value = "implEncrypt") static int implEncrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, true, false); @@ -108,7 +109,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false) static int decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false); @@ -121,7 +122,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false) static int implDecrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, false); @@ -138,7 +139,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false, value = "decrypt") static int decryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true); @@ -154,7 +155,7 @@ public class CipherBlockChainingSubstitutions { @MethodSubstitution(isStatic = false, value = "implDecrypt") static int implDecryptWithOriginalKey(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); - Object embeddedCipher = UnsafeLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); + Object embeddedCipher = RawLoadNode.load(realReceiver, embeddedCipherOffset, JavaKind.Object, LocationIdentity.any()); if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { Object aesCipher = getAESCryptClass().cast(embeddedCipher); crypt(realReceiver, in, inOffset, inLength, out, outOffset, aesCipher, false, true); @@ -168,17 +169,17 @@ public class CipherBlockChainingSubstitutions { AESCryptSubstitutions.checkArgs(in, inOffset, out, outOffset); Object realReceiver = PiNode.piCastNonNull(rcvr, cipherBlockChainingClass); Object aesCipher = getAESCryptClass().cast(embeddedCipher); - Object kObject = UnsafeLoadNode.load(aesCipher, AESCryptSubstitutions.kOffset, JavaKind.Object, LocationIdentity.any()); - Object rObject = UnsafeLoadNode.load(realReceiver, rOffset, JavaKind.Object, LocationIdentity.any()); + Object kObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.kOffset, JavaKind.Object, LocationIdentity.any()); + Object rObject = RawLoadNode.load(realReceiver, rOffset, JavaKind.Object, LocationIdentity.any()); Pointer kAddr = Word.objectToTrackedPointer(kObject).add(getArrayBaseOffset(JavaKind.Int)); Pointer rAddr = Word.objectToTrackedPointer(rObject).add(getArrayBaseOffset(JavaKind.Byte)); - Word inAddr = Word.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(JavaKind.Byte) + inOffset)); - Word outAddr = Word.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(JavaKind.Byte) + outOffset)); + Word inAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(in, getArrayBaseOffset(JavaKind.Byte) + inOffset)); + Word outAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(out, getArrayBaseOffset(JavaKind.Byte) + outOffset)); if (encrypt) { encryptAESCryptStub(ENCRYPT, inAddr, outAddr, kAddr, rAddr, inLength); } else { if (withOriginalKey) { - Object lastKeyObject = UnsafeLoadNode.load(aesCipher, AESCryptSubstitutions.lastKeyOffset, JavaKind.Object, LocationIdentity.any()); + Object lastKeyObject = RawLoadNode.load(aesCipher, AESCryptSubstitutions.lastKeyOffset, JavaKind.Object, LocationIdentity.any()); Pointer lastKeyAddr = Word.objectToTrackedPointer(lastKeyObject).add(getArrayBaseOffset(JavaKind.Byte)); decryptAESCryptWithOriginalKeyStub(DECRYPT_WITH_ORIGINAL_KEY, inAddr, outAddr, kAddr, rAddr, inLength, lastKeyAddr); } else { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java index ea6af4de1f2..a385134ccb4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java @@ -22,11 +22,14 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; -import org.graalvm.compiler.core.common.LocationIdentity; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaMethod; + import org.graalvm.compiler.core.common.calc.Condition; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.graph.spi.Canonicalizable; @@ -35,16 +38,19 @@ import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.FloatingGuardedNode; +import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ConvertNode; +import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.extended.GetClassNode; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.memory.ReadNode; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantReflectionProvider; @@ -58,33 +64,40 @@ import jdk.vm.ci.meta.ResolvedJavaType; * handled by * {@link ReadNode#canonicalizeRead(ValueNode, AddressNode, LocationIdentity, CanonicalizerTool)}. */ -@NodeInfo(cycles = CYCLES_4, size = SIZE_1) -public final class ClassGetHubNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode { +@NodeInfo(cycles = CYCLES_1, size = SIZE_1) +public final class ClassGetHubNode extends FloatingNode implements Lowerable, Canonicalizable, ConvertNode { public static final NodeClass TYPE = NodeClass.create(ClassGetHubNode.class); @Input protected ValueNode clazz; public ClassGetHubNode(ValueNode clazz) { - this(clazz, null); - } - - public ClassGetHubNode(ValueNode clazz, ValueNode guard) { - super(TYPE, KlassPointerStamp.klass(), (GuardingNode) guard); + super(TYPE, KlassPointerStamp.klass()); this.clazz = clazz; } - @Override - public Node canonical(CanonicalizerTool tool) { - if (tool.allUsagesAvailable() && hasNoUsages()) { + public static ValueNode create(ValueNode clazz, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean allUsagesAvailable) { + return canonical(null, metaAccess, constantReflection, allUsagesAvailable, KlassPointerStamp.klass(), clazz); + } + + @SuppressWarnings("unused") + public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode clazz) { + ValueNode clazzValue = create(clazz, b.getMetaAccess(), b.getConstantReflection(), false); + b.push(JavaKind.Object, b.append(clazzValue)); + return true; + } + + public static ValueNode canonical(ClassGetHubNode classGetHubNode, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, boolean allUsagesAvailable, Stamp stamp, + ValueNode clazz) { + ClassGetHubNode self = classGetHubNode; + if (allUsagesAvailable && self != null && self.hasNoUsages()) { return null; } else { if (clazz.isConstant()) { - MetaAccessProvider metaAccess = tool.getMetaAccess(); if (metaAccess != null) { - ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(clazz.asJavaConstant()); + ResolvedJavaType exactType = constantReflection.asJavaType(clazz.asJavaConstant()); if (exactType.isPrimitive()) { - return ConstantNode.forConstant(stamp(), JavaConstant.NULL_POINTER, metaAccess); + return ConstantNode.forConstant(stamp, JavaConstant.NULL_POINTER, metaAccess); } else { - return ConstantNode.forConstant(stamp(), tool.getConstantReflection().asObjectHub(exactType), metaAccess); + return ConstantNode.forConstant(stamp, constantReflection.asObjectHub(exactType), metaAccess); } } } @@ -93,23 +106,31 @@ public final class ClassGetHubNode extends FloatingGuardedNode implements Lowera return new LoadHubNode(KlassPointerStamp.klassNonNull(), getClass.getObject()); } if (clazz instanceof HubGetClassNode) { - // replace _klass._java_mirror._klass -> _klass + // Replace: _klass._java_mirror._klass -> _klass return ((HubGetClassNode) clazz).getHub(); } - return this; + if (self == null) { + self = new ClassGetHubNode(clazz); + } + return self; } } + @Override + public Node canonical(CanonicalizerTool tool) { + return canonical(this, tool.getMetaAccess(), tool.getConstantReflection(), tool.allUsagesAvailable(), stamp(), clazz); + } + @Override public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); } @NodeIntrinsic - public static native KlassPointer readClass(Class clazz); + public static native KlassPointer readClass(Class clazzNonNull); - @NodeIntrinsic - public static native KlassPointer readClass(Class clazz, GuardingNode guard); + @NodeIntrinsic(PiNode.class) + public static native KlassPointer piCastNonNull(Object object, GuardingNode anchor); @Override public ValueNode getValue() { @@ -138,6 +159,14 @@ public final class ClassGetHubNode extends FloatingGuardedNode implements Lowera return false; } + /** + * There is more than one {@link java.lang.Class} value that has a NULL hub. + */ + @Override + public boolean mayNullCheckSkipConversion() { + return false; + } + @Override public boolean preservesOrder(Condition op, Constant value, ConstantReflectionProvider constantReflection) { assert op == Condition.EQ || op == Condition.NE; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java index 301b03d12a6..9341f650207 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/EncodedSymbolConstant.java @@ -26,7 +26,7 @@ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.nio.ByteBuffer; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.type.DataPointerConstant; import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java index f0608fdafbb..6ea1cf5bcb4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java @@ -36,15 +36,18 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.word.Word; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.TargetDescription; @@ -63,7 +66,7 @@ public class HashCodeSnippets implements Snippets { // this code is independent from biased locking (although it does not look that way) final Word biasedLock = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)); - if (probability(FAST_PATH_PROBABILITY, biasedLock.equal(Word.unsigned(unlockedMask(INJECTED_VMCONFIG))))) { + if (probability(FAST_PATH_PROBABILITY, biasedLock.equal(WordFactory.unsigned(unlockedMask(INJECTED_VMCONFIG))))) { int hash = (int) mark.unsignedShiftRight(identityHashCodeShift(INJECTED_VMCONFIG)).rawValue(); if (probability(FAST_PATH_PROBABILITY, hash != uninitializedIdentityHashCodeValue(INJECTED_VMCONFIG))) { return hash; @@ -76,15 +79,15 @@ public class HashCodeSnippets implements Snippets { private final SnippetInfo identityHashCodeSnippet = snippet(HashCodeSnippets.class, "identityHashCodeSnippet", HotSpotReplacementsUtil.MARK_WORD_LOCATION); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); } public void lower(IdentityHashCodeNode node, LoweringTool tool) { StructuredGraph graph = node.graph(); Arguments args = new Arguments(identityHashCodeSnippet, graph.getGuardsStage(), tool.getLoweringStage()); args.add("thisObj", node.object); - SnippetTemplate template = template(args); + SnippetTemplate template = template(node.getDebug(), args); template.instantiate(providers.getMetaAccess(), node, SnippetTemplate.DEFAULT_REPLACER, args); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotClassSubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotClassSubstitutions.java index 8113802a62a..0a53eb454f1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotClassSubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotClassSubstitutions.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitution; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.PiNode; +import org.graalvm.compiler.nodes.SnippetAnchorNode; // JaCoCo Exclude @@ -78,7 +79,8 @@ public class HotSpotClassSubstitutions { // Class for primitive type return false; } else { - return klassIsArray(klass); + KlassPointer klassNonNull = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor()); + return klassIsArray(klassNonNull); } } @@ -92,16 +94,18 @@ public class HotSpotClassSubstitutions { public static Class getSuperclass(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); if (!klass.isNull()) { - int accessFlags = klass.readInt(klassAccessFlagsOffset(INJECTED_VMCONFIG), KLASS_ACCESS_FLAGS_LOCATION); + KlassPointer klassNonNull = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor()); + int accessFlags = klassNonNull.readInt(klassAccessFlagsOffset(INJECTED_VMCONFIG), KLASS_ACCESS_FLAGS_LOCATION); if ((accessFlags & Modifier.INTERFACE) == 0) { - if (klassIsArray(klass)) { + if (klassIsArray(klassNonNull)) { return Object.class; } else { - KlassPointer superKlass = klass.readKlassPointer(klassSuperKlassOffset(INJECTED_VMCONFIG), KLASS_SUPER_KLASS_LOCATION); + KlassPointer superKlass = klassNonNull.readKlassPointer(klassSuperKlassOffset(INJECTED_VMCONFIG), KLASS_SUPER_KLASS_LOCATION); if (superKlass.isNull()) { return null; } else { - return readJavaMirror(superKlass); + KlassPointer superKlassNonNull = ClassGetHubNode.piCastNonNull(superKlass, SnippetAnchorNode.anchor()); + return HubGetClassNode.readClass(superKlassNonNull); } } } @@ -111,16 +115,13 @@ public class HotSpotClassSubstitutions { return null; } - public static Class readJavaMirror(KlassPointer klass) { - return PiNode.asNonNullClass(HubGetClassNode.readClass(klass)); - } - @MethodSubstitution(isStatic = false) public static Class getComponentType(final Class thisObj) { KlassPointer klass = ClassGetHubNode.readClass(thisObj); if (!klass.isNull()) { - if (klassIsArray(klass)) { - return PiNode.asNonNullClass(klass.readObject(arrayKlassComponentMirrorOffset(INJECTED_VMCONFIG), ARRAY_KLASS_COMPONENT_MIRROR)); + KlassPointer klassNonNull = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor()); + if (klassIsArray(klassNonNull)) { + return PiNode.asNonNullClass(klassNonNull.readObject(arrayKlassComponentMirrorOffset(INJECTED_VMCONFIG), ARRAY_KLASS_COMPONENT_MIRROR)); } } else { // Class for primitive type diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java index 90c34836d4e..37e7c1826a8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java @@ -22,15 +22,14 @@ */ package org.graalvm.compiler.hotspot.replacements; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.VERIFY_OOP; import static org.graalvm.compiler.hotspot.replacements.UnsafeAccess.UNSAFE; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.SuppressFBWarnings; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.ObjectStamp; @@ -40,19 +39,17 @@ import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; -import org.graalvm.compiler.hotspot.nodes.SnippetAnchorNode; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.CanonicalizableLocation; +import org.graalvm.compiler.nodes.CompressionNode; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.extended.StoreHubNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; import org.graalvm.compiler.nodes.memory.Access; import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; @@ -61,6 +58,8 @@ import org.graalvm.compiler.replacements.ReplacementsUtil; import org.graalvm.compiler.replacements.nodes.ReadRegisterNode; import org.graalvm.compiler.replacements.nodes.WriteRegisterNode; import org.graalvm.compiler.word.Word; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.code.Register; @@ -389,32 +388,23 @@ public class HotSpotReplacementsUtil { return config.klassLayoutHelperOffset; } - public static int readLayoutHelper(KlassPointer hub) { - // return hub.readInt(klassLayoutHelperOffset(), KLASS_LAYOUT_HELPER_LOCATION); - GuardingNode anchorNode = SnippetAnchorNode.anchor(); - return loadKlassLayoutHelperIntrinsic(hub, anchorNode); - } - @NodeIntrinsic(value = KlassLayoutHelperNode.class) - public static native int loadKlassLayoutHelperIntrinsic(KlassPointer object, GuardingNode anchor); - - @NodeIntrinsic(value = KlassLayoutHelperNode.class) - public static native int loadKlassLayoutHelperIntrinsic(KlassPointer object); + public static native int readLayoutHelper(KlassPointer object); /** * Checks if class {@code klass} is an array. * * See: Klass::layout_helper_is_array * - * @param klass the class to be checked - * @return true if klass is an array, false otherwise + * @param klassNonNull the class to be checked + * @return true if klassNonNull is an array, false otherwise */ - public static boolean klassIsArray(KlassPointer klass) { + public static boolean klassIsArray(KlassPointer klassNonNull) { /* * The less-than check only works if both values are ints. We use local variables to make * sure these are still ints and haven't changed. */ - final int layoutHelper = readLayoutHelper(klass); + final int layoutHelper = readLayoutHelper(klassNonNull); final int layoutHelperNeutralValue = config(INJECTED_VMCONFIG).klassLayoutHelperNeutralValue; return (layoutHelper < layoutHelperNeutralValue); } @@ -479,6 +469,31 @@ public class HotSpotReplacementsUtil { return config.unlockedMask; } + @Fold + public static int monitorMask(@InjectedParameter GraalHotSpotVMConfig config) { + return config.monitorMask; + } + + @Fold + public static int objectMonitorOwnerOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorOwner; + } + + @Fold + public static int objectMonitorRecursionsOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorRecursions; + } + + @Fold + public static int objectMonitorCxqOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorCxq; + } + + @Fold + public static int objectMonitorEntryListOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorEntryList; + } + /** * Mask for a biasable, locked or unlocked mark word. * @@ -545,7 +560,7 @@ public class HotSpotReplacementsUtil { } public static Word arrayStart(int[] a) { - return Word.unsigned(ComputeObjectAddressNode.get(a, getArrayBaseOffset(JavaKind.Int))); + return WordFactory.unsigned(ComputeObjectAddressNode.get(a, getArrayBaseOffset(JavaKind.Int))); } @Fold @@ -626,6 +641,14 @@ public class HotSpotReplacementsUtil { public static final LocationIdentity DISPLACED_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("DisplacedMarkWord"); + public static final LocationIdentity OBJECT_MONITOR_OWNER_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_owner"); + + public static final LocationIdentity OBJECT_MONITOR_RECURSION_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_recursions"); + + public static final LocationIdentity OBJECT_MONITOR_CXQ_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_cxq"); + + public static final LocationIdentity OBJECT_MONITOR_ENTRY_LIST_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_EntryList"); + @Fold public static int lockDisplacedMarkOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.basicLockDisplacedHeaderOffset; @@ -680,17 +703,17 @@ public class HotSpotReplacementsUtil { public static Word loadWordFromObject(Object object, int offset) { ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject"); - return loadWordFromObjectIntrinsic(object, offset, getWordKind(), LocationIdentity.any()); + return loadWordFromObjectIntrinsic(object, offset, LocationIdentity.any(), getWordKind()); } public static Word loadWordFromObject(Object object, int offset, LocationIdentity identity) { ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject"); - return loadWordFromObjectIntrinsic(object, offset, getWordKind(), identity); + return loadWordFromObjectIntrinsic(object, offset, identity, getWordKind()); } public static KlassPointer loadKlassFromObject(Object object, int offset, LocationIdentity identity) { ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject"); - return loadKlassFromObjectIntrinsic(object, offset, getWordKind(), identity); + return loadKlassFromObjectIntrinsic(object, offset, identity, getWordKind()); } /** @@ -703,17 +726,17 @@ public class HotSpotReplacementsUtil { return registerAsWord(register, true, false); } - @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = ReadRegisterNode.class) public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming); - @NodeIntrinsic(value = WriteRegisterNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = WriteRegisterNode.class) public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value); - @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) - private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity); + @NodeIntrinsic(value = RawLoadNode.class) + private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter JavaKind wordKind); - @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) - private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity); + @NodeIntrinsic(value = RawLoadNode.class) + private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter LocationIdentity locationIdentity, @ConstantNodeParameter JavaKind wordKind); @NodeIntrinsic(value = LoadHubNode.class) public static native KlassPointer loadHubIntrinsic(Object object); @@ -781,6 +804,8 @@ public class HotSpotReplacementsUtil { public static final LocationIdentity CLASS_MIRROR_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror"); + public static final LocationIdentity CLASS_MIRROR_HANDLE_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror handle"); + public static final LocationIdentity HEAP_TOP_LOCATION = NamedLocationIdentity.mutable("HeapTop"); @Fold diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotspotSnippetsOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotspotSnippetsOptions.java index 94724505f30..e22020218bb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotspotSnippetsOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotspotSnippetsOptions.java @@ -23,10 +23,10 @@ package org.graalvm.compiler.hotspot.replacements; import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.ProfileContext; -import org.graalvm.compiler.options.EnumOptionValue; +import org.graalvm.compiler.options.EnumOptionKey; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; /** * Options related to HotSpot snippets in this package. @@ -39,31 +39,34 @@ public class HotspotSnippetsOptions { // @formatter:off @Option(help = "If the probability that a type check will hit one the profiled types (up to " + "TypeCheckMaxHints) is below this value, the type check will be compiled without profiling info", type = OptionType.Expert) - public static final OptionValue TypeCheckMinProfileHitProbability = new OptionValue<>(0.5); + public static final OptionKey TypeCheckMinProfileHitProbability = new OptionKey<>(0.5); @Option(help = "The maximum number of profiled types that will be used when compiling a profiled type check. " + "Note that TypeCheckMinProfileHitProbability also influences whether profiling info is used in compiled type checks.", type = OptionType.Expert) - public static final OptionValue TypeCheckMaxHints = new OptionValue<>(2); + public static final OptionKey TypeCheckMaxHints = new OptionKey<>(2); @Option(help = "Use a VM runtime call to load and clear the exception object from the thread at the start of a compiled exception handler.", type = OptionType.Debug) - public static final OptionValue LoadExceptionObjectInVM = new OptionValue<>(false); + public static final OptionKey LoadExceptionObjectInVM = new OptionKey<>(false); @Option(help = "Enable profiling of allocation sites.", type = OptionType.Debug) - public static final OptionValue ProfileAllocations = new OptionValue<>(false); + public static final OptionKey ProfileAllocations = new OptionKey<>(false); @Option(help = "Control the naming of the counters when using ProfileAllocations.", type = OptionType.Debug) - public static final EnumOptionValue ProfileAllocationsContext = new EnumOptionValue<>(ProfileContext.AllocatingMethod); + public static final EnumOptionKey ProfileAllocationsContext = new EnumOptionKey<>(ProfileContext.AllocatingMethod); @Option(help = "Enable profiling of monitor operations.", type = OptionType.Debug) - public static final OptionValue ProfileMonitors = new OptionValue<>(false); + public static final OptionKey ProfileMonitors = new OptionKey<>(false); + + @Option(help = "Handle simple cases for inflated monitors in the fast-path.", type = OptionType.Expert) + public static final OptionKey SimpleFastInflatedLocking = new OptionKey<>(true); @Option(help = "Trace monitor operations on objects whose type contains this substring.", type = OptionType.Debug) - public static final OptionValue TraceMonitorsTypeFilter = new OptionValue<>(null); + public static final OptionKey TraceMonitorsTypeFilter = new OptionKey<>(null); @Option(help = "Trace monitor operations in methods whose fully qualified name contains this substring.", type = OptionType.Debug) - public static final OptionValue TraceMonitorsMethodFilter = new OptionValue<>(null); + public static final OptionKey TraceMonitorsMethodFilter = new OptionKey<>(null); @Option(help = "Emit extra code to dynamically check monitor operations are balanced.", type = OptionType.Debug) - public static final OptionValue VerifyBalancedMonitors = new OptionValue<>(false); + public static final OptionKey VerifyBalancedMonitors = new OptionKey<>(false); //@formatter:on } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java index 647b8d0c7c5..c96dc5c3654 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HubGetClassNode.java @@ -22,9 +22,10 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; +import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.graph.Node; @@ -34,9 +35,9 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.FloatingGuardedNode; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.calc.ConvertNode; +import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -50,13 +51,13 @@ import jdk.vm.ci.meta.ResolvedJavaType; * Read {@code Klass::_java_mirror} and incorporate non-null type information into stamp. This is * also used by {@link ClassGetHubNode} to eliminate chains of {@code klass._java_mirror._klass}. */ -@NodeInfo(cycles = CYCLES_4, size = SIZE_1) -public final class HubGetClassNode extends FloatingGuardedNode implements Lowerable, Canonicalizable, ConvertNode { +@NodeInfo(cycles = CYCLES_1, size = SIZE_1) +public final class HubGetClassNode extends FloatingNode implements Lowerable, Canonicalizable, ConvertNode { public static final NodeClass TYPE = NodeClass.create(HubGetClassNode.class); @Input protected ValueNode hub; public HubGetClassNode(@InjectedNodeParameter MetaAccessProvider metaAccess, ValueNode hub) { - super(TYPE, StampFactory.objectNonNull(TypeReference.createWithoutAssumptions(metaAccess.lookupJavaType(Class.class))), null); + super(TYPE, StampFactory.objectNonNull(TypeReference.createWithoutAssumptions(metaAccess.lookupJavaType(Class.class)))); this.hub = hub; } @@ -70,7 +71,7 @@ public final class HubGetClassNode extends FloatingGuardedNode implements Lowera return null; } else { MetaAccessProvider metaAccess = tool.getMetaAccess(); - if (metaAccess != null && hub.isConstant()) { + if (metaAccess != null && hub.isConstant() && !GraalOptions.ImmutableCode.getValue(graph().getOptions())) { ResolvedJavaType exactType = tool.getConstantReflection().asJavaType(hub.asConstant()); if (exactType != null) { return ConstantNode.forConstant(tool.getConstantReflection().asJavaClass(exactType), metaAccess); @@ -114,11 +115,16 @@ public final class HubGetClassNode extends FloatingGuardedNode implements Lowera } } + /** + * Any concrete Klass* has a corresponding {@link java.lang.Class}. + */ @Override public boolean isLossless() { - /* - * Any concrete Klass* has a corresponding java.lang.Class - */ + return true; + } + + @Override + public boolean mayNullCheckSkipConversion() { return true; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java index 9c1da836f4a..2577987d090 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java @@ -26,7 +26,6 @@ import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode; import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.type.AbstractObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.Node; @@ -40,6 +39,7 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.JavaConstant; @@ -67,7 +67,7 @@ public class IdentityHashCodeNode extends FixedWithNextNode implements Canonical if (object.isConstant()) { assert object.stamp() instanceof AbstractObjectStamp; JavaConstant c = (JavaConstant) object.asConstant(); - if (ImmutableCode.getValue()) { + if (ImmutableCode.getValue(getOptions())) { return this; } JavaConstant identityHashCode = null; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java index 177b159f9ec..29453e464ce 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java @@ -22,6 +22,8 @@ */ package org.graalvm.compiler.hotspot.replacements; +import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; +import static jdk.vm.ci.meta.DeoptimizationReason.OptimizedTypeCheckViolated; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PRIMARY_SUPERS_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.SECONDARY_SUPER_CACHE_LOCATION; @@ -31,34 +33,28 @@ import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.T import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.checkSecondarySubType; import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.checkUnknownSubType; import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.createHints; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.displayHit; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.displayMiss; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.exactHit; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.exactMiss; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.hintsHit; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.hintsMiss; -import static org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.isNull; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LIKELY_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_LIKELY_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; -import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; -import static jdk.vm.ci.meta.DeoptimizationReason.OptimizedTypeCheckViolated; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter; import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter; +import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.SnippetAnchorNode; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; +import org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.Counters; import org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.Hints; -import org.graalvm.compiler.hotspot.replacements.aot.ResolveConstantSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DeoptimizeNode; import org.graalvm.compiler.nodes.PiNode; +import org.graalvm.compiler.nodes.SnippetAnchorNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.TypeCheckHints; import org.graalvm.compiler.nodes.ValueNode; @@ -68,7 +64,9 @@ import org.graalvm.compiler.nodes.java.ClassIsAssignableFromNode; import org.graalvm.compiler.nodes.java.InstanceOfDynamicNode; import org.graalvm.compiler.nodes.java.InstanceOfNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.InstanceOfSnippetsTemplates; +import org.graalvm.compiler.replacements.SnippetCounter; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; @@ -99,9 +97,9 @@ public class InstanceOfSnippets implements Snippets { */ @Snippet public static Object instanceofWithProfile(Object object, @VarargsParameter KlassPointer[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue, - @ConstantParameter boolean nullSeen) { + @ConstantParameter boolean nullSeen, @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); if (!nullSeen) { // See comment below for other deoptimization path; the // same reasoning applies here. @@ -117,10 +115,10 @@ public class InstanceOfSnippets implements Snippets { KlassPointer hintHub = hints[i]; boolean positive = hintIsPositive[i]; if (probability(LIKELY_PROBABILITY, hintHub.equal(objectHub))) { - hintsHit.inc(); + counters.hintsHit.inc(); return positive ? trueValue : falseValue; } - hintsMiss.inc(); + counters.hintsMiss.inc(); } // This maybe just be a rare event but it might also indicate a phase change // in the application. Ideally we want to use DeoptimizationAction.None for @@ -134,59 +132,48 @@ public class InstanceOfSnippets implements Snippets { * A test against a final type. */ @Snippet - public static Object instanceofExact(Object object, KlassPointer exactHub, Object trueValue, Object falseValue) { + public static Object instanceofExact(Object object, KlassPointer exactHub, Object trueValue, Object falseValue, @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); if (probability(LIKELY_PROBABILITY, objectHub.notEqual(exactHub))) { - exactMiss.inc(); + counters.exactMiss.inc(); return falseValue; } - exactHit.inc(); + counters.exactHit.inc(); return trueValue; } - @Snippet - public static Object instanceofExactPIC(Object object, KlassPointer exactHub, Object trueValue, Object falseValue) { - KlassPointer exactHubPIC = ResolveConstantSnippets.resolveKlassConstant(exactHub); - return instanceofExact(object, exactHubPIC, trueValue, falseValue); - } - /** * A test against a primary type. */ @Snippet - public static Object instanceofPrimary(KlassPointer hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue) { + public static Object instanceofPrimary(KlassPointer hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); if (probability(NOT_LIKELY_PROBABILITY, objectHub.readKlassPointer(superCheckOffset, PRIMARY_SUPERS_LOCATION).notEqual(hub))) { - displayMiss.inc(); + counters.displayMiss.inc(); return falseValue; } - displayHit.inc(); + counters.displayHit.inc(); return trueValue; } - @Snippet - public static Object instanceofPrimaryPIC(KlassPointer hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue) { - KlassPointer resolvedHub = ResolveConstantSnippets.resolveKlassConstant(hub); - return instanceofPrimary(resolvedHub, object, superCheckOffset, trueValue, falseValue); - } - /** * A test against a restricted secondary type type. */ @Snippet - public static Object instanceofSecondary(KlassPointer hub, Object object, @VarargsParameter KlassPointer[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue) { + public static Object instanceofSecondary(KlassPointer hub, Object object, @VarargsParameter KlassPointer[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, Object falseValue, + @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); return falseValue; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); @@ -197,31 +184,24 @@ public class InstanceOfSnippets implements Snippets { KlassPointer hintHub = hints[i]; boolean positive = hintIsPositive[i]; if (probability(NOT_FREQUENT_PROBABILITY, hintHub.equal(objectHub))) { - hintsHit.inc(); + counters.hintsHit.inc(); return positive ? trueValue : falseValue; } } - hintsMiss.inc(); - if (!checkSecondarySubType(hub, objectHub)) { + counters.hintsMiss.inc(); + if (!checkSecondarySubType(hub, objectHub, counters)) { return falseValue; } return trueValue; } - @Snippet - public static Object instanceofSecondaryPIC(KlassPointer hub, Object object, @VarargsParameter KlassPointer[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue, - Object falseValue) { - KlassPointer resolvedHub = ResolveConstantSnippets.resolveKlassConstant(hub); - return instanceofSecondary(resolvedHub, object, hints, hintIsPositive, trueValue, falseValue); - } - /** * Type test used when the type being tested against is not known at compile time. */ @Snippet - public static Object instanceofDynamic(KlassPointer hub, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean allowNull) { + public static Object instanceofDynamic(KlassPointer hub, Object object, Object trueValue, Object falseValue, @ConstantParameter boolean allowNull, @ConstantParameter Counters counters) { if (probability(NOT_FREQUENT_PROBABILITY, object == null)) { - isNull.inc(); + counters.isNull.inc(); if (allowNull) { return trueValue; } else { @@ -229,47 +209,60 @@ public class InstanceOfSnippets implements Snippets { } } GuardingNode anchorNode = SnippetAnchorNode.anchor(); - KlassPointer objectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); + KlassPointer nonNullObjectHub = loadHubIntrinsic(PiNode.piCastNonNull(object, anchorNode)); // The hub of a primitive type can be null => always return false in this case. - if (hub.isNull() || !checkUnknownSubType(hub, objectHub)) { - return falseValue; + if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !hub.isNull())) { + if (checkUnknownSubType(hub, nonNullObjectHub, counters)) { + return trueValue; + } } - return trueValue; + return falseValue; } @Snippet - public static Object isAssignableFrom(Class thisClass, Class otherClass, Object trueValue, Object falseValue) { - if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_FREQUENT_PROBABILITY, otherClass == null)) { + public static Object isAssignableFrom(@NonNullParameter Class thisClassNonNull, Class otherClass, Object trueValue, Object falseValue, @ConstantParameter Counters counters) { + if (otherClass == null) { DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); return false; } GuardingNode anchorNode = SnippetAnchorNode.anchor(); - KlassPointer thisHub = ClassGetHubNode.readClass(thisClass, anchorNode); - KlassPointer otherHub = ClassGetHubNode.readClass(otherClass, anchorNode); - if (thisHub.isNull() || otherHub.isNull()) { - // primitive types, only true if equal. - return thisClass == otherClass ? trueValue : falseValue; + Class otherClassNonNull = PiNode.piCastNonNullClass(otherClass, anchorNode); + + if (BranchProbabilityNode.probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, thisClassNonNull == otherClassNonNull)) { + return trueValue; } - if (!TypeCheckSnippetUtils.checkUnknownSubType(thisHub, otherHub)) { - return falseValue; + + KlassPointer thisHub = ClassGetHubNode.readClass(thisClassNonNull); + KlassPointer otherHub = ClassGetHubNode.readClass(otherClassNonNull); + if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !thisHub.isNull())) { + if (BranchProbabilityNode.probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, !otherHub.isNull())) { + GuardingNode guardNonNull = SnippetAnchorNode.anchor(); + KlassPointer nonNullOtherHub = ClassGetHubNode.piCastNonNull(otherHub, guardNonNull); + if (TypeCheckSnippetUtils.checkUnknownSubType(thisHub, nonNullOtherHub, counters)) { + return trueValue; + } + } } - return trueValue; + + // If either hub is null, one of them is a primitive type and given that the class is not + // equal, return false. + return falseValue; } public static class Templates extends InstanceOfSnippetsTemplates { private final SnippetInfo instanceofWithProfile = snippet(InstanceOfSnippets.class, "instanceofWithProfile"); private final SnippetInfo instanceofExact = snippet(InstanceOfSnippets.class, "instanceofExact"); - private final SnippetInfo instanceofExactPIC = snippet(InstanceOfSnippets.class, "instanceofExactPIC"); private final SnippetInfo instanceofPrimary = snippet(InstanceOfSnippets.class, "instanceofPrimary"); - private final SnippetInfo instanceofPrimaryPIC = snippet(InstanceOfSnippets.class, "instanceofPrimaryPIC"); private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary", SECONDARY_SUPER_CACHE_LOCATION); - private final SnippetInfo instanceofSecondaryPIC = snippet(InstanceOfSnippets.class, "instanceofSecondaryPIC", SECONDARY_SUPER_CACHE_LOCATION); private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic", SECONDARY_SUPER_CACHE_LOCATION); private final SnippetInfo isAssignableFrom = snippet(InstanceOfSnippets.class, "isAssignableFrom", SECONDARY_SUPER_CACHE_LOCATION); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + private final Counters counters; + + public Templates(OptionValues options, Iterable factories, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); + this.counters = new Counters(factory); } @Override @@ -279,13 +272,15 @@ public class InstanceOfSnippets implements Snippets { ValueNode object = instanceOf.getValue(); Assumptions assumptions = instanceOf.graph().getAssumptions(); + OptionValues localOptions = instanceOf.getOptions(); JavaTypeProfile profile = instanceOf.profile(); - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(localOptions)) { // FIXME: We can't embed constants in hints. We can't really load them from GOT // either. Hard problem. profile = null; } - TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), profile, assumptions, TypeCheckMinProfileHitProbability.getValue(), TypeCheckMaxHints.getValue()); + TypeCheckHints hintInfo = new TypeCheckHints(instanceOf.type(), profile, assumptions, TypeCheckMinProfileHitProbability.getValue(localOptions), + TypeCheckMaxHints.getValue(localOptions)); final HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) instanceOf.type().getType(); ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), type.klass(), providers.getMetaAccess(), instanceOf.graph()); @@ -299,20 +294,17 @@ public class InstanceOfSnippets implements Snippets { args.addVarargs("hints", KlassPointer.class, KlassPointerStamp.klassNonNull(), hints.hubs); args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(JavaKind.Boolean), hints.isPositive); } else if (hintInfo.exact != null) { - SnippetInfo snippet = GeneratePIC.getValue() ? instanceofExactPIC : instanceofExact; - args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); + args = new Arguments(instanceofExact, graph.getGuardsStage(), tool.getLoweringStage()); args.add("object", object); args.add("exactHub", ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) hintInfo.exact).klass(), providers.getMetaAccess(), graph)); } else if (type.isPrimaryType()) { - SnippetInfo snippet = GeneratePIC.getValue() ? instanceofPrimaryPIC : instanceofPrimary; - args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); + args = new Arguments(instanceofPrimary, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.add("object", object); args.addConst("superCheckOffset", type.superCheckOffset()); } else { Hints hints = createHints(hintInfo, providers.getMetaAccess(), false, graph); - SnippetInfo snippet = GeneratePIC.getValue() ? instanceofSecondaryPIC : instanceofSecondary; - args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); + args = new Arguments(instanceofSecondary, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.add("object", object); args.addVarargs("hints", KlassPointer.class, KlassPointerStamp.klassNonNull(), hints.hubs); @@ -323,6 +315,7 @@ public class InstanceOfSnippets implements Snippets { if (hintInfo.hintHitProbability >= 1.0 && hintInfo.exact == null) { args.addConst("nullSeen", hintInfo.profile.getNullSeen() != TriState.FALSE); } + args.addConst("counters", counters); return args; } else if (replacer.instanceOf instanceof InstanceOfDynamicNode) { InstanceOfDynamicNode instanceOf = (InstanceOfDynamicNode) replacer.instanceOf; @@ -334,14 +327,17 @@ public class InstanceOfSnippets implements Snippets { args.add("trueValue", replacer.trueValue); args.add("falseValue", replacer.falseValue); args.addConst("allowNull", instanceOf.allowsNull()); + args.addConst("counters", counters); return args; } else if (replacer.instanceOf instanceof ClassIsAssignableFromNode) { ClassIsAssignableFromNode isAssignable = (ClassIsAssignableFromNode) replacer.instanceOf; Arguments args = new Arguments(isAssignableFrom, isAssignable.graph().getGuardsStage(), tool.getLoweringStage()); - args.add("thisClass", isAssignable.getThisClass()); + assert ((ObjectStamp) isAssignable.getThisClass().stamp()).nonNull(); + args.add("thisClassNonNull", isAssignable.getThisClass()); args.add("otherClass", isAssignable.getOtherClass()); args.add("trueValue", replacer.trueValue); args.add("falseValue", replacer.falseValue); + args.addConst("counters", counters); return args; } else { throw GraalError.shouldNotReachHere(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java index 346c94ff104..7cbcd3887f9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/KlassLayoutHelperNode.java @@ -22,9 +22,12 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -35,10 +38,10 @@ import org.graalvm.compiler.graph.spi.CanonicalizerTool; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.FloatingGuardedNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; +import org.graalvm.compiler.nodes.calc.FloatingNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; +import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; @@ -51,21 +54,29 @@ import jdk.vm.ci.meta.ResolvedJavaType; * Read {@code Klass::_layout_helper} and incorporate any useful stamp information based on any type * information in {@code klass}. */ -@NodeInfo(cycles = CYCLES_4, size = SIZE_1) -public final class KlassLayoutHelperNode extends FloatingGuardedNode implements Canonicalizable, Lowerable { +@NodeInfo(cycles = CYCLES_1, size = SIZE_1) +public final class KlassLayoutHelperNode extends FloatingNode implements Canonicalizable, Lowerable { public static final NodeClass TYPE = NodeClass.create(KlassLayoutHelperNode.class); @Input protected ValueNode klass; protected final GraalHotSpotVMConfig config; public KlassLayoutHelperNode(@InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass) { - this(config, klass, null); + super(TYPE, StampFactory.forKind(JavaKind.Int)); + this.config = config; + this.klass = klass; } - public KlassLayoutHelperNode(@InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass, ValueNode guard) { - super(TYPE, StampFactory.forKind(JavaKind.Int), (GuardingNode) guard); - this.klass = klass; - this.config = config; + public static ValueNode create(GraalHotSpotVMConfig config, ValueNode klass, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess) { + Stamp stamp = StampFactory.forKind(JavaKind.Int); + return canonical(null, config, klass, stamp, constantReflection, metaAccess); + } + + @SuppressWarnings("unused") + public static boolean intrinsify(GraphBuilderContext b, ResolvedJavaMethod method, @InjectedNodeParameter GraalHotSpotVMConfig config, ValueNode klass) { + ValueNode valueNode = create(config, klass, b.getConstantReflection(), b.getMetaAccess()); + b.push(JavaKind.Int, b.append(valueNode)); + return true; } @Override @@ -97,29 +108,38 @@ public final class KlassLayoutHelperNode extends FloatingGuardedNode implements if (tool.allUsagesAvailable() && hasNoUsages()) { return null; } else { - if (klass.isConstant()) { - if (!klass.asConstant().isDefaultForKind()) { - Constant constant = stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), klass.asConstant(), config.klassLayoutHelperOffset); - return ConstantNode.forConstant(stamp(), constant, tool.getMetaAccess()); - } - } - if (klass instanceof LoadHubNode) { - LoadHubNode hub = (LoadHubNode) klass; - Stamp hubStamp = hub.getValue().stamp(); - if (hubStamp instanceof ObjectStamp) { - ObjectStamp ostamp = (ObjectStamp) hubStamp; - HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) ostamp.type(); - if (type != null && type.isArray() && !type.getComponentType().isPrimitive()) { - // The layout for all object arrays is the same. - Constant constant = stamp().readConstant(tool.getConstantReflection().getMemoryAccessProvider(), type.klass(), config.klassLayoutHelperOffset); - return ConstantNode.forConstant(stamp(), constant, tool.getMetaAccess()); - } - } - } - return this; + return canonical(this, config, klass, stamp(), tool.getConstantReflection(), tool.getMetaAccess()); } } + private static ValueNode canonical(KlassLayoutHelperNode klassLayoutHelperNode, GraalHotSpotVMConfig config, ValueNode klass, Stamp stamp, ConstantReflectionProvider constantReflection, + MetaAccessProvider metaAccess) { + KlassLayoutHelperNode self = klassLayoutHelperNode; + if (klass.isConstant()) { + if (!klass.asConstant().isDefaultForKind()) { + Constant constant = stamp.readConstant(constantReflection.getMemoryAccessProvider(), klass.asConstant(), config.klassLayoutHelperOffset); + return ConstantNode.forConstant(stamp, constant, metaAccess); + } + } + if (klass instanceof LoadHubNode) { + LoadHubNode hub = (LoadHubNode) klass; + Stamp hubStamp = hub.getValue().stamp(); + if (hubStamp instanceof ObjectStamp) { + ObjectStamp ostamp = (ObjectStamp) hubStamp; + HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) ostamp.type(); + if (type != null && type.isArray() && !type.getComponentType().isPrimitive()) { + // The layout for all object arrays is the same. + Constant constant = stamp.readConstant(constantReflection.getMemoryAccessProvider(), type.klass(), config.klassLayoutHelperOffset); + return ConstantNode.forConstant(stamp, constant, metaAccess); + } + } + } + if (self == null) { + self = new KlassLayoutHelperNode(config, klass); + } + return self; + } + @Override public void lower(LoweringTool tool) { tool.getLowerer().lower(this, tool); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java index 02eaf651a88..69e547306ec 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java @@ -29,28 +29,34 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeExceptionOop; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeExceptionPc; -import static org.graalvm.compiler.nodes.PiNode.piCast; +import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.LoadExceptionObjectInVM; +import static org.graalvm.compiler.nodes.PiNode.piCastToSnippetReplaceeStamp; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; +import org.graalvm.compiler.hotspot.word.HotSpotWordTypes; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.java.LoadExceptionObjectNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.replacements.nodes.ReadRegisterNode; import org.graalvm.compiler.word.Word; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.ResolvedJavaType; /** * Snippet for loading the exception object at the start of an exception dispatcher. @@ -63,32 +69,31 @@ import jdk.vm.ci.code.TargetDescription; */ public class LoadExceptionObjectSnippets implements Snippets { - /** - * Alternative way to implement exception object loading. - */ - private static final boolean USE_C_RUNTIME = HotspotSnippetsOptions.LoadExceptionObjectInVM.getValue(); - @Snippet public static Object loadException(@ConstantParameter Register threadRegister) { Word thread = registerAsWord(threadRegister); Object exception = readExceptionOop(thread); writeExceptionOop(thread, null); - writeExceptionPc(thread, Word.zero()); - return piCast(exception, StampFactory.forNodeIntrinsic()); + writeExceptionPc(thread, WordFactory.zero()); + return piCastToSnippetReplaceeStamp(exception); } public static class Templates extends AbstractTemplates { private final SnippetInfo loadException = snippet(LoadExceptionObjectSnippets.class, "loadException", EXCEPTION_OOP_LOCATION, EXCEPTION_PC_LOCATION); + private final HotSpotWordTypes wordTypes; - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); + this.wordTypes = providers.getWordTypes(); } public void lower(LoadExceptionObjectNode loadExceptionObject, HotSpotRegistersProvider registers, LoweringTool tool) { - if (USE_C_RUNTIME) { - StructuredGraph graph = loadExceptionObject.graph(); - ReadRegisterNode thread = graph.add(new ReadRegisterNode(registers.getThreadRegister(), true, false)); + StructuredGraph graph = loadExceptionObject.graph(); + if (LoadExceptionObjectInVM.getValue(graph.getOptions())) { + ResolvedJavaType wordType = providers.getMetaAccess().lookupJavaType(Word.class); + Stamp stamp = wordTypes.getWordStamp(wordType); + ReadRegisterNode thread = graph.add(new ReadRegisterNode(stamp, registers.getThreadRegister(), true, false)); graph.addBeforeFixed(loadExceptionObject, thread); ForeignCallNode loadExceptionC = graph.add(new ForeignCallNode(providers.getForeignCalls(), LOAD_AND_CLEAR_EXCEPTION, thread)); loadExceptionC.setStateAfter(loadExceptionObject.stateAfter()); @@ -96,7 +101,7 @@ public class LoadExceptionObjectSnippets implements Snippets { } else { Arguments args = new Arguments(loadException, loadExceptionObject.graph().getGuardsStage(), tool.getLoweringStage()); args.addConst("threadRegister", registers.getThreadRegister()); - template(args).instantiate(providers.getMetaAccess(), loadExceptionObject, DEFAULT_REPLACER, args); + template(loadExceptionObject.getDebug(), args).instantiate(providers.getMetaAccess(), loadExceptionObject, DEFAULT_REPLACER, args); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java index 91747913671..83a6060d95d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java @@ -22,14 +22,18 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; +import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE; +import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.nodes.BeginLockScopeNode.beginLockScope; -import static org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode.compareAndSwap; import static org.graalvm.compiler.hotspot.nodes.EndLockScopeNode.endLockScope; import static org.graalvm.compiler.hotspot.nodes.VMErrorNode.vmError; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.DISPLACED_MARK_WORD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.MARK_WORD_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_CXQ_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_ENTRY_LIST_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_OWNER_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_RECURSION_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.ageMaskInPlace; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.biasedLockMaskInPlace; @@ -39,6 +43,11 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadWordFromObject; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.lockDisplacedMarkOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.markOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.monitorMask; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorCxqOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorEntryListOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorOwnerOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorRecursionsOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.pageSize; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.prototypeMarkWordOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; @@ -47,12 +56,16 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOop; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileMonitors; +import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.SimpleFastInflatedLocking; import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.TraceMonitorsMethodFilter; import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.TraceMonitorsTypeFilter; import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.VerifyBalancedMonitors; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_LIKELY_PROBABILITY; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_FAST_PATH_PROBABILITY; -import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; @@ -63,19 +76,19 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.graph.iterators.NodeIterable; +import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; import org.graalvm.compiler.hotspot.nodes.AcquiredCASLockNode; import org.graalvm.compiler.hotspot.nodes.CurrentLockNode; -import org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode; import org.graalvm.compiler.hotspot.nodes.FastAcquireBiasedLockNode; import org.graalvm.compiler.hotspot.nodes.MonitorCounterNode; import org.graalvm.compiler.hotspot.word.KlassPointer; @@ -90,14 +103,14 @@ import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.debug.DynamicCounterNode; -import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; +import org.graalvm.compiler.nodes.extended.MembarNode; import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.nodes.java.MonitorExitNode; import org.graalvm.compiler.nodes.java.RawMonitorEnterNode; -import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.type.StampTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.common.inlining.InliningUtil; import org.graalvm.compiler.replacements.Log; import org.graalvm.compiler.replacements.SnippetCounter; @@ -106,7 +119,10 @@ import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.word.Word; -import org.graalvm.compiler.word.WordBase; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.Pointer; +import org.graalvm.word.WordBase; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.Register; @@ -114,7 +130,6 @@ import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.DeoptimizationAction; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; /** @@ -201,13 +216,13 @@ public class MonitorSnippets implements Snippets { private static final boolean PROFILE_CONTEXT = false; @Fold - static boolean doProfile() { - return ProfileMonitors.getValue(); + static boolean doProfile(OptionValues options) { + return ProfileMonitors.getValue(options); } @Snippet public static void monitorenter(Object object, KlassPointer hub, @ConstantParameter int lockDepth, @ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister, - @ConstantParameter boolean trace) { + @ConstantParameter boolean trace, @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { verifyOop(object); // Load the mark word - this includes a null-check on object @@ -215,197 +230,256 @@ public class MonitorSnippets implements Snippets { final Word lock = beginLockScope(lockDepth); - trace(trace, " object: 0x%016lx\n", Word.objectToTrackedPointer(object)); + Pointer objectPointer = Word.objectToTrackedPointer(object); + trace(trace, " object: 0x%016lx\n", objectPointer); trace(trace, " lock: 0x%016lx\n", lock); trace(trace, " mark: 0x%016lx\n", mark); - incCounter(); + incCounter(options); if (useBiasedLocking(INJECTED_VMCONFIG)) { - // See whether the lock is currently biased toward our thread and - // whether the epoch is still valid. - // Note that the runtime guarantees sufficient alignment of JavaThread - // pointers to allow age to be placed into low bits. - final Word biasableLockBits = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)); - - // Check whether the bias pattern is present in the object's mark word - // and the bias owner and the epoch are both still current. - final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); - final Word thread = registerAsWord(threadRegister); - final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace(INJECTED_VMCONFIG)); - trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord); - trace(trace, " thread: 0x%016lx\n", thread); - trace(trace, " tmp: 0x%016lx\n", tmp); - if (probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, tmp.equal(0))) { - // Object is already biased to current thread -> done - traceObject(trace, "+lock{bias:existing}", object, true); - lockBiasExisting.inc(); - FastAcquireBiasedLockNode.mark(object); + if (tryEnterBiased(object, hub, lock, mark, threadRegister, trace, options, counters)) { return; } - - // Now check to see whether biasing is enabled for this object - if (probability(BranchProbabilityNode.FAST_PATH_PROBABILITY, biasableLockBits.notEqual(Word.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) { - // Biasing not enabled -> fall through to lightweight locking - unbiasable.inc(); - } else { - // At this point we know that the mark word has the bias pattern and - // that we are not the bias owner in the current epoch. We need to - // figure out more details about the state of the mark word in order to - // know what operations can be legally performed on the object's - // mark word. - - // If the low three bits in the xor result aren't clear, that means - // the prototype header is no longer biasable and we have to revoke - // the bias on this object. - if (probability(FREQUENT_PROBABILITY, tmp.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(0))) { - // Biasing is still enabled for object's type. See whether the - // epoch of the current bias is still valid, meaning that the epoch - // bits of the mark word are equal to the epoch bits of the - // prototype mark word. (Note that the prototype mark word's epoch bits - // only change at a safepoint.) If not, attempt to rebias the object - // toward the current thread. Note that we must be absolutely sure - // that the current epoch is invalid in order to do this because - // otherwise the manipulations it performs on the mark word are - // illegal. - if (probability(FREQUENT_PROBABILITY, tmp.and(epochMaskInPlace(INJECTED_VMCONFIG)).equal(0))) { - // The epoch of the current bias is still valid but we know nothing - // about the owner; it might be set or it might be clear. Try to - // acquire the bias of the object using an atomic operation. If this - // fails we will go in to the runtime to revoke the object's bias. - // Note that we first construct the presumed unbiased header so we - // don't accidentally blow away another thread's valid bias. - Word unbiasedMark = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG) | ageMaskInPlace(INJECTED_VMCONFIG) | epochMaskInPlace(INJECTED_VMCONFIG)); - Word biasedMark = unbiasedMark.or(thread); - trace(trace, " unbiasedMark: 0x%016lx\n", unbiasedMark); - trace(trace, " biasedMark: 0x%016lx\n", biasedMark); - if (probability(VERY_FAST_PATH_PROBABILITY, - compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), unbiasedMark, biasedMark, MARK_WORD_LOCATION).equal(unbiasedMark))) { - // Object is now biased to current thread -> done - traceObject(trace, "+lock{bias:acquired}", object, true); - lockBiasAcquired.inc(); - return; - } - // If the biasing toward our thread failed, this means that another thread - // owns the bias and we need to revoke that bias. The revocation will occur - // in the interpreter runtime. - traceObject(trace, "+lock{stub:revoke}", object, true); - lockStubRevoke.inc(); - } else { - // At this point we know the epoch has expired, meaning that the - // current bias owner, if any, is actually invalid. Under these - // circumstances _only_, are we allowed to use the current mark word - // value as the comparison value when doing the CAS to acquire the - // bias in the current epoch. In other words, we allow transfer of - // the bias from one thread to another directly in this situation. - Word biasedMark = prototypeMarkWord.or(thread); - trace(trace, " biasedMark: 0x%016lx\n", biasedMark); - if (probability(VERY_FAST_PATH_PROBABILITY, - compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), mark, biasedMark, MARK_WORD_LOCATION).equal(mark))) { - // Object is now biased to current thread -> done - traceObject(trace, "+lock{bias:transfer}", object, true); - lockBiasTransfer.inc(); - return; - } - // If the biasing toward our thread failed, then another thread - // succeeded in biasing it toward itself and we need to revoke that - // bias. The revocation will occur in the runtime in the slow case. - traceObject(trace, "+lock{stub:epoch-expired}", object, true); - lockStubEpochExpired.inc(); - } - monitorenterStubC(MONITORENTER, object, lock); - return; - } else { - // The prototype mark word doesn't have the bias bit set any - // more, indicating that objects of this data type are not supposed - // to be biased any more. We are going to try to reset the mark of - // this object to the prototype value and fall through to the - // CAS-based locking scheme. Note that if our CAS fails, it means - // that another thread raced us for the privilege of revoking the - // bias of this particular object, so it's okay to continue in the - // normal locking code. - Word result = compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), mark, prototypeMarkWord, MARK_WORD_LOCATION); - - // Fall through to the normal CAS-based lock, because no matter what - // the result of the above CAS, some thread must have succeeded in - // removing the bias bit from the object's header. - - if (ENABLE_BREAKPOINT) { - bkpt(object, mark, tmp, result); - } - revokeBias.inc(); - } - } + // not biased, fall-through } - - // Create the unlocked mark word pattern - Word unlockedMark = mark.or(unlockedMask(INJECTED_VMCONFIG)); - trace(trace, " unlockedMark: 0x%016lx\n", unlockedMark); - - // Copy this unlocked mark word into the lock slot on the stack - lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), unlockedMark, DISPLACED_MARK_WORD_LOCATION); - - // Test if the object's mark word is unlocked, and if so, store the - // (address of) the lock slot into the object's mark word. - Word currentMark = compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), unlockedMark, lock, MARK_WORD_LOCATION); - if (probability(BranchProbabilityNode.SLOW_PATH_PROBABILITY, currentMark.notEqual(unlockedMark))) { - trace(trace, " currentMark: 0x%016lx\n", currentMark); - // The mark word in the object header was not the same. - // Either the object is locked by another thread or is already locked - // by the current thread. The latter is true if the mark word - // is a stack pointer into the current thread's stack, i.e.: - // - // 1) (currentMark & aligned_mask) == 0 - // 2) rsp <= currentMark - // 3) currentMark <= rsp + page_size - // - // These 3 tests can be done by evaluating the following expression: - // - // (currentMark - rsp) & (aligned_mask - page_size) - // - // assuming both the stack pointer and page_size have their least - // significant 2 bits cleared and page_size is a power of 2 - final Word alignedMask = Word.unsigned(wordSize() - 1); - final Word stackPointer = registerAsWord(stackPointerRegister).add(config(INJECTED_VMCONFIG).stackBias); - if (probability(VERY_SLOW_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).notEqual(0))) { - // Most likely not a recursive lock, go into a slow runtime call - traceObject(trace, "+lock{stub:failed-cas}", object, true); - lockStubFailedCas.inc(); - monitorenterStubC(MONITORENTER, object, lock); + if (inlineFastLockSupported(options) && probability(SLOW_PATH_PROBABILITY, mark.and(monitorMask(INJECTED_VMCONFIG)).notEqual(0))) { + // Inflated case + if (tryEnterInflated(object, lock, mark, threadRegister, trace, options, counters)) { return; - } else { - // Recursively locked => write 0 to the lock slot - lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), Word.zero(), DISPLACED_MARK_WORD_LOCATION); - traceObject(trace, "+lock{cas:recursive}", object, true); - lockCasRecursive.inc(); } } else { - traceObject(trace, "+lock{cas}", object, true); - lockCas.inc(); - AcquiredCASLockNode.mark(object); + // Create the unlocked mark word pattern + Word unlockedMark = mark.or(unlockedMask(INJECTED_VMCONFIG)); + trace(trace, " unlockedMark: 0x%016lx\n", unlockedMark); + + // Copy this unlocked mark word into the lock slot on the stack + lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), unlockedMark, DISPLACED_MARK_WORD_LOCATION); + + // make sure previous store does not float below compareAndSwap + MembarNode.memoryBarrier(STORE_STORE); + + // Test if the object's mark word is unlocked, and if so, store the + // (address of) the lock slot into the object's mark word. + Word currentMark = objectPointer.compareAndSwapWord(markOffset(INJECTED_VMCONFIG), unlockedMark, lock, MARK_WORD_LOCATION); + if (probability(FAST_PATH_PROBABILITY, currentMark.equal(unlockedMark))) { + traceObject(trace, "+lock{cas}", object, true, options); + counters.lockCas.inc(); + AcquiredCASLockNode.mark(object); + return; + } else { + trace(trace, " currentMark: 0x%016lx\n", currentMark); + // The mark word in the object header was not the same. + // Either the object is locked by another thread or is already locked + // by the current thread. The latter is true if the mark word + // is a stack pointer into the current thread's stack, i.e.: + // + // 1) (currentMark & aligned_mask) == 0 + // 2) rsp <= currentMark + // 3) currentMark <= rsp + page_size + // + // These 3 tests can be done by evaluating the following expression: + // + // (currentMark - rsp) & (aligned_mask - page_size) + // + // assuming both the stack pointer and page_size have their least + // significant 2 bits cleared and page_size is a power of 2 + final Word alignedMask = WordFactory.unsigned(wordSize() - 1); + final Word stackPointer = registerAsWord(stackPointerRegister).add(config(INJECTED_VMCONFIG).stackBias); + if (probability(FAST_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize())).equal(0))) { + // Recursively locked => write 0 to the lock slot + lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), WordFactory.zero(), DISPLACED_MARK_WORD_LOCATION); + traceObject(trace, "+lock{cas:recursive}", object, true, options); + counters.lockCasRecursive.inc(); + return; + } + traceObject(trace, "+lock{stub:failed-cas/stack}", object, true, options); + counters.lockStubFailedCas.inc(); + } } + // slow-path runtime-call + monitorenterStubC(MONITORENTER, object, lock); + } + + private static boolean tryEnterBiased(Object object, KlassPointer hub, Word lock, Word mark, Register threadRegister, boolean trace, OptionValues options, Counters counters) { + // See whether the lock is currently biased toward our thread and + // whether the epoch is still valid. + // Note that the runtime guarantees sufficient alignment of JavaThread + // pointers to allow age to be placed into low bits. + final Word biasableLockBits = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)); + + // Check whether the bias pattern is present in the object's mark word + // and the bias owner and the epoch are both still current. + final Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); + final Word thread = registerAsWord(threadRegister); + final Word tmp = prototypeMarkWord.or(thread).xor(mark).and(~ageMaskInPlace(INJECTED_VMCONFIG)); + trace(trace, "prototypeMarkWord: 0x%016lx\n", prototypeMarkWord); + trace(trace, " thread: 0x%016lx\n", thread); + trace(trace, " tmp: 0x%016lx\n", tmp); + if (probability(FAST_PATH_PROBABILITY, tmp.equal(0))) { + // Object is already biased to current thread -> done + traceObject(trace, "+lock{bias:existing}", object, true, options); + counters.lockBiasExisting.inc(); + FastAcquireBiasedLockNode.mark(object); + return true; + } + + // Now check to see whether biasing is enabled for this object + if (probability(NOT_FREQUENT_PROBABILITY, biasableLockBits.equal(WordFactory.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) { + Pointer objectPointer = Word.objectToTrackedPointer(object); + // At this point we know that the mark word has the bias pattern and + // that we are not the bias owner in the current epoch. We need to + // figure out more details about the state of the mark word in order to + // know what operations can be legally performed on the object's + // mark word. + + // If the low three bits in the xor result aren't clear, that means + // the prototype header is no longer biasable and we have to revoke + // the bias on this object. + if (probability(FREQUENT_PROBABILITY, tmp.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(0))) { + // Biasing is still enabled for object's type. See whether the + // epoch of the current bias is still valid, meaning that the epoch + // bits of the mark word are equal to the epoch bits of the + // prototype mark word. (Note that the prototype mark word's epoch bits + // only change at a safepoint.) If not, attempt to rebias the object + // toward the current thread. Note that we must be absolutely sure + // that the current epoch is invalid in order to do this because + // otherwise the manipulations it performs on the mark word are + // illegal. + if (probability(FREQUENT_PROBABILITY, tmp.and(epochMaskInPlace(INJECTED_VMCONFIG)).equal(0))) { + // The epoch of the current bias is still valid but we know nothing + // about the owner; it might be set or it might be clear. Try to + // acquire the bias of the object using an atomic operation. If this + // fails we will go in to the runtime to revoke the object's bias. + // Note that we first construct the presumed unbiased header so we + // don't accidentally blow away another thread's valid bias. + Word unbiasedMark = mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG) | ageMaskInPlace(INJECTED_VMCONFIG) | epochMaskInPlace(INJECTED_VMCONFIG)); + Word biasedMark = unbiasedMark.or(thread); + trace(trace, " unbiasedMark: 0x%016lx\n", unbiasedMark); + trace(trace, " biasedMark: 0x%016lx\n", biasedMark); + if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), unbiasedMark, biasedMark, MARK_WORD_LOCATION))) { + // Object is now biased to current thread -> done + traceObject(trace, "+lock{bias:acquired}", object, true, options); + counters.lockBiasAcquired.inc(); + return true; + } + // If the biasing toward our thread failed, this means that another thread + // owns the bias and we need to revoke that bias. The revocation will occur + // in the interpreter runtime. + traceObject(trace, "+lock{stub:revoke}", object, true, options); + counters.lockStubRevoke.inc(); + } else { + // At this point we know the epoch has expired, meaning that the + // current bias owner, if any, is actually invalid. Under these + // circumstances _only_, are we allowed to use the current mark word + // value as the comparison value when doing the CAS to acquire the + // bias in the current epoch. In other words, we allow transfer of + // the bias from one thread to another directly in this situation. + Word biasedMark = prototypeMarkWord.or(thread); + trace(trace, " biasedMark: 0x%016lx\n", biasedMark); + if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), mark, biasedMark, MARK_WORD_LOCATION))) { + // Object is now biased to current thread -> done + traceObject(trace, "+lock{bias:transfer}", object, true, options); + counters.lockBiasTransfer.inc(); + return true; + } + // If the biasing toward our thread failed, then another thread + // succeeded in biasing it toward itself and we need to revoke that + // bias. The revocation will occur in the runtime in the slow case. + traceObject(trace, "+lock{stub:epoch-expired}", object, true, options); + counters.lockStubEpochExpired.inc(); + } + // slow-path runtime-call + monitorenterStubC(MONITORENTER, object, lock); + return true; + } else { + // The prototype mark word doesn't have the bias bit set any + // more, indicating that objects of this data type are not supposed + // to be biased any more. We are going to try to reset the mark of + // this object to the prototype value and fall through to the + // CAS-based locking scheme. Note that if our CAS fails, it means + // that another thread raced us for the privilege of revoking the + // bias of this particular object, so it's okay to continue in the + // normal locking code. + Word result = objectPointer.compareAndSwapWord(markOffset(INJECTED_VMCONFIG), mark, prototypeMarkWord, MARK_WORD_LOCATION); + + // Fall through to the normal CAS-based lock, because no matter what + // the result of the above CAS, some thread must have succeeded in + // removing the bias bit from the object's header. + + if (ENABLE_BREAKPOINT) { + bkpt(object, mark, tmp, result); + } + counters.revokeBias.inc(); + return false; + } + } else { + // Biasing not enabled -> fall through to lightweight locking + counters.unbiasable.inc(); + return false; + } + } + + @Fold + public static boolean useFastInflatedLocking(OptionValues options) { + return SimpleFastInflatedLocking.getValue(options); + } + + private static boolean inlineFastLockSupported(OptionValues options) { + return inlineFastLockSupported(INJECTED_VMCONFIG, options); + } + + private static boolean inlineFastLockSupported(GraalHotSpotVMConfig config, OptionValues options) { + return useFastInflatedLocking(options) && monitorMask(config) >= 0 && objectMonitorOwnerOffset(config) >= 0; + } + + private static boolean tryEnterInflated(Object object, Word lock, Word mark, Register threadRegister, boolean trace, OptionValues options, Counters counters) { + // write non-zero value to lock slot + lock.writeWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), lock, DISPLACED_MARK_WORD_LOCATION); + // mark is a pointer to the ObjectMonitor + monitorMask + Word monitor = mark.subtract(monitorMask(INJECTED_VMCONFIG)); + int ownerOffset = objectMonitorOwnerOffset(INJECTED_VMCONFIG); + Word owner = monitor.readWord(ownerOffset, OBJECT_MONITOR_OWNER_LOCATION); + if (probability(FREQUENT_PROBABILITY, owner.equal(0))) { + // it appears unlocked (owner == 0) + if (probability(FREQUENT_PROBABILITY, monitor.logicCompareAndSwapWord(ownerOffset, owner, registerAsWord(threadRegister), OBJECT_MONITOR_OWNER_LOCATION))) { + // success + traceObject(trace, "+lock{inflated:cas}", object, true, options); + counters.inflatedCas.inc(); + return true; + } else { + traceObject(trace, "+lock{stub:inflated:failed-cas}", object, true, options); + counters.inflatedFailedCas.inc(); + } + } else { + traceObject(trace, "+lock{stub:inflated:owned}", object, true, options); + counters.inflatedOwned.inc(); + } + return false; } /** * Calls straight out to the monitorenter stub. */ @Snippet - public static void monitorenterStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) { + public static void monitorenterStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace, @ConstantParameter OptionValues options) { verifyOop(object); - incCounter(); + incCounter(options); if (object == null) { DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); } // BeginLockScope nodes do not read from object so a use of object // cannot float about the null check above final Word lock = beginLockScope(lockDepth); - traceObject(trace, "+lock{stub}", object, true); + traceObject(trace, "+lock{stub}", object, true, options); monitorenterStubC(MONITORENTER, object, lock); } @Snippet - public static void monitorexit(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) { + public static void monitorexit(Object object, @ConstantParameter int lockDepth, @ConstantParameter Register threadRegister, @ConstantParameter boolean trace, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { trace(trace, " object: 0x%016lx\n", Word.objectToTrackedPointer(object)); + final Word mark = loadWordFromObject(object, markOffset(INJECTED_VMCONFIG)); if (useBiasedLocking(INJECTED_VMCONFIG)) { // Check for biased locking unlock case, which is a no-op // Note: we do not have to check the thread ID for two reasons. @@ -413,13 +487,12 @@ public class MonitorSnippets implements Snippets { // a higher level. Second, if the bias was revoked while we held the // lock, the object could not be rebiased toward another thread, so // the bias bit would be clear. - final Word mark = loadWordFromObject(object, markOffset(INJECTED_VMCONFIG)); trace(trace, " mark: 0x%016lx\n", mark); - if (probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(Word.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) { + if (probability(FREQUENT_PROBABILITY, mark.and(biasedLockMaskInPlace(INJECTED_VMCONFIG)).equal(WordFactory.unsigned(biasedLockPattern(INJECTED_VMCONFIG))))) { endLockScope(); - decCounter(); - traceObject(trace, "-lock{bias}", object, false); - unlockBias.inc(); + decCounter(options); + traceObject(trace, "-lock{bias}", object, false, options); + counters.unlockBias.inc(); return; } } @@ -430,46 +503,95 @@ public class MonitorSnippets implements Snippets { final Word displacedMark = lock.readWord(lockDisplacedMarkOffset(INJECTED_VMCONFIG), DISPLACED_MARK_WORD_LOCATION); trace(trace, " displacedMark: 0x%016lx\n", displacedMark); - if (probability(BranchProbabilityNode.NOT_LIKELY_PROBABILITY, displacedMark.equal(0))) { + if (probability(NOT_LIKELY_PROBABILITY, displacedMark.equal(0))) { // Recursive locking => done - traceObject(trace, "-lock{recursive}", object, false); - unlockCasRecursive.inc(); + traceObject(trace, "-lock{recursive}", object, false, options); + counters.unlockCasRecursive.inc(); } else { - verifyOop(object); - // Test if object's mark word is pointing to the displaced mark word, and if so, restore - // the displaced mark in the object - if the object's mark word is not pointing to - // the displaced mark word, do unlocking via runtime call. - if (probability(VERY_SLOW_PATH_PROBABILITY, - DirectCompareAndSwapNode.compareAndSwap(OffsetAddressNode.address(object, markOffset(INJECTED_VMCONFIG)), lock, displacedMark, MARK_WORD_LOCATION).notEqual(lock))) { - // The object's mark word was not pointing to the displaced header, - // we do unlocking via runtime call. - traceObject(trace, "-lock{stub}", object, false); - unlockStub.inc(); - monitorexitStubC(MONITOREXIT, object, lock); - } else { - traceObject(trace, "-lock{cas}", object, false); - unlockCas.inc(); + if (!tryExitInflated(object, mark, lock, threadRegister, trace, options, counters)) { + verifyOop(object); + // Test if object's mark word is pointing to the displaced mark word, and if so, + // restore + // the displaced mark in the object - if the object's mark word is not pointing to + // the displaced mark word, do unlocking via runtime call. + Pointer objectPointer = Word.objectToTrackedPointer(object); + if (probability(VERY_FAST_PATH_PROBABILITY, objectPointer.logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), lock, displacedMark, MARK_WORD_LOCATION))) { + traceObject(trace, "-lock{cas}", object, false, options); + counters.unlockCas.inc(); + } else { + // The object's mark word was not pointing to the displaced header + traceObject(trace, "-lock{stub}", object, false, options); + counters.unlockStub.inc(); + monitorexitStubC(MONITOREXIT, object, lock); + } } } endLockScope(); - decCounter(); + decCounter(options); + } + + private static boolean inlineFastUnlockSupported(OptionValues options) { + return inlineFastUnlockSupported(INJECTED_VMCONFIG, options); + } + + private static boolean inlineFastUnlockSupported(GraalHotSpotVMConfig config, OptionValues options) { + return useFastInflatedLocking(options) && objectMonitorEntryListOffset(config) >= 0 && objectMonitorCxqOffset(config) >= 0 && monitorMask(config) >= 0 && + objectMonitorOwnerOffset(config) >= 0 && objectMonitorRecursionsOffset(config) >= 0; + } + + private static boolean tryExitInflated(Object object, Word mark, Word lock, Register threadRegister, boolean trace, OptionValues options, Counters counters) { + if (!inlineFastUnlockSupported(options)) { + return false; + } + if (probability(SLOW_PATH_PROBABILITY, mark.and(monitorMask(INJECTED_VMCONFIG)).notEqual(0))) { + // Inflated case + // mark is a pointer to the ObjectMonitor + monitorMask + Word monitor = mark.subtract(monitorMask(INJECTED_VMCONFIG)); + int ownerOffset = objectMonitorOwnerOffset(INJECTED_VMCONFIG); + Word owner = monitor.readWord(ownerOffset, OBJECT_MONITOR_OWNER_LOCATION); + int recursionsOffset = objectMonitorRecursionsOffset(INJECTED_VMCONFIG); + Word recursions = monitor.readWord(recursionsOffset, OBJECT_MONITOR_RECURSION_LOCATION); + Word thread = registerAsWord(threadRegister); + if (probability(FAST_PATH_PROBABILITY, owner.xor(thread).or(recursions).equal(0))) { + // owner == thread && recursions == 0 + int cxqOffset = objectMonitorCxqOffset(INJECTED_VMCONFIG); + Word cxq = monitor.readWord(cxqOffset, OBJECT_MONITOR_CXQ_LOCATION); + int entryListOffset = objectMonitorEntryListOffset(INJECTED_VMCONFIG); + Word entryList = monitor.readWord(entryListOffset, OBJECT_MONITOR_ENTRY_LIST_LOCATION); + if (probability(FREQUENT_PROBABILITY, cxq.or(entryList).equal(0))) { + // cxq == 0 && entryList == 0 + // Nobody is waiting, success + // release_store + MembarNode.memoryBarrier(LOAD_STORE | STORE_STORE); + monitor.writeWord(ownerOffset, WordFactory.zero()); + traceObject(trace, "-lock{inflated:simple}", object, false, options); + counters.unlockInflatedSimple.inc(); + return true; + } + } + counters.unlockStubInflated.inc(); + traceObject(trace, "-lock{stub:inflated}", object, false, options); + monitorexitStubC(MONITOREXIT, object, lock); + return true; + } + return false; } /** * Calls straight out to the monitorexit stub. */ @Snippet - public static void monitorexitStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace) { + public static void monitorexitStub(Object object, @ConstantParameter int lockDepth, @ConstantParameter boolean trace, @ConstantParameter OptionValues options) { verifyOop(object); - traceObject(trace, "-lock{stub}", object, false); + traceObject(trace, "-lock{stub}", object, false, options); final Word lock = CurrentLockNode.currentLock(lockDepth); monitorexitStubC(MONITOREXIT, object, lock); endLockScope(); - decCounter(); + decCounter(options); } - public static void traceObject(boolean enabled, String action, Object object, boolean enter) { - if (doProfile()) { + public static void traceObject(boolean enabled, String action, Object object, boolean enter, OptionValues options) { + if (doProfile(options)) { DynamicCounterNode.counter(action, enter ? "number of monitor enters" : "number of monitor exits", 1, PROFILE_CONTEXT); } if (enabled) { @@ -496,18 +618,21 @@ public class MonitorSnippets implements Snippets { @NodeIntrinsic(BreakpointNode.class) static native void bkpt(Object object, Word mark, Word tmp, Word value); - private static final boolean VERIFY_BALANCED_MONITORS = VerifyBalancedMonitors.getValue(); + @Fold + static boolean verifyBalancedMonitors(OptionValues options) { + return VerifyBalancedMonitors.getValue(options); + } - public static void incCounter() { - if (VERIFY_BALANCED_MONITORS) { + public static void incCounter(OptionValues options) { + if (verifyBalancedMonitors(options)) { final Word counter = MonitorCounterNode.counter(); final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION); counter.writeInt(0, count + 1, MONITOR_COUNTER_LOCATION); } } - public static void decCounter() { - if (VERIFY_BALANCED_MONITORS) { + public static void decCounter(OptionValues options) { + if (verifyBalancedMonitors(options)) { final Word counter = MonitorCounterNode.counter(); final int count = counter.readInt(0, MONITOR_COUNTER_LOCATION); counter.writeInt(0, count - 1, MONITOR_COUNTER_LOCATION); @@ -529,6 +654,64 @@ public class MonitorSnippets implements Snippets { } } + public static class Counters { + /** + * Counters for the various paths for acquiring a lock. The counters whose names start with + * {@code "lock"} are mutually exclusive. The other counters are for paths that may be + * shared. + */ + public final SnippetCounter lockBiasExisting; + public final SnippetCounter lockBiasAcquired; + public final SnippetCounter lockBiasTransfer; + public final SnippetCounter lockCas; + public final SnippetCounter lockCasRecursive; + public final SnippetCounter lockStubEpochExpired; + public final SnippetCounter lockStubRevoke; + public final SnippetCounter lockStubFailedCas; + public final SnippetCounter inflatedCas; + public final SnippetCounter inflatedFailedCas; + public final SnippetCounter inflatedOwned; + public final SnippetCounter unbiasable; + public final SnippetCounter revokeBias; + + /** + * Counters for the various paths for releasing a lock. The counters whose names start with + * {@code "unlock"} are mutually exclusive. The other counters are for paths that may be + * shared. + */ + public final SnippetCounter unlockBias; + public final SnippetCounter unlockCas; + public final SnippetCounter unlockCasRecursive; + public final SnippetCounter unlockStub; + public final SnippetCounter unlockStubInflated; + public final SnippetCounter unlockInflatedSimple; + + public Counters(SnippetCounter.Group.Factory factory) { + SnippetCounter.Group enter = factory.createSnippetCounterGroup("MonitorEnters"); + SnippetCounter.Group exit = factory.createSnippetCounterGroup("MonitorExits"); + lockBiasExisting = new SnippetCounter(enter, "lock{bias:existing}", "bias-locked previously biased object"); + lockBiasAcquired = new SnippetCounter(enter, "lock{bias:acquired}", "bias-locked newly biased object"); + lockBiasTransfer = new SnippetCounter(enter, "lock{bias:transfer}", "bias-locked, biased transferred"); + lockCas = new SnippetCounter(enter, "lock{cas}", "cas-locked an object"); + lockCasRecursive = new SnippetCounter(enter, "lock{cas:recursive}", "cas-locked, recursive"); + lockStubEpochExpired = new SnippetCounter(enter, "lock{stub:epoch-expired}", "stub-locked, epoch expired"); + lockStubRevoke = new SnippetCounter(enter, "lock{stub:revoke}", "stub-locked, biased revoked"); + lockStubFailedCas = new SnippetCounter(enter, "lock{stub:failed-cas/stack}", "stub-locked, failed cas and stack locking"); + inflatedCas = new SnippetCounter(enter, "lock{inflated:cas}", "heavyweight-locked, cas-locked"); + inflatedFailedCas = new SnippetCounter(enter, "lock{inflated:failed-cas}", "heavyweight-locked, failed cas"); + inflatedOwned = new SnippetCounter(enter, "lock{inflated:owned}", "heavyweight-locked, already owned"); + unbiasable = new SnippetCounter(enter, "unbiasable", "object with unbiasable type"); + revokeBias = new SnippetCounter(enter, "revokeBias", "object had bias revoked"); + + unlockBias = new SnippetCounter(exit, "unlock{bias}", "bias-unlocked an object"); + unlockCas = new SnippetCounter(exit, "unlock{cas}", "cas-unlocked an object"); + unlockCasRecursive = new SnippetCounter(exit, "unlock{cas:recursive}", "cas-unlocked an object, recursive"); + unlockStub = new SnippetCounter(exit, "unlock{stub}", "stub-unlocked an object"); + unlockStubInflated = new SnippetCounter(exit, "unlock{stub:inflated}", "stub-unlocked an object with inflated monitor"); + unlockInflatedSimple = new SnippetCounter(exit, "unlock{inflated}", "unlocked an object monitor"); + } + } + public static class Templates extends AbstractTemplates { private final SnippetInfo monitorenter = snippet(MonitorSnippets.class, "monitorenter"); @@ -539,10 +722,14 @@ public class MonitorSnippets implements Snippets { private final SnippetInfo checkCounter = snippet(MonitorSnippets.class, "checkCounter"); private final boolean useFastLocking; + public final Counters counters; - public Templates(HotSpotProviders providers, TargetDescription target, boolean useFastLocking) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, + boolean useFastLocking) { + super(options, factories, providers, providers.getSnippetReflection(), target); this.useFastLocking = useFastLocking; + + this.counters = new Counters(factory); } public void lower(RawMonitorEnterNode monitorenterNode, HotSpotRegistersProvider registers, LoweringTool tool) { @@ -559,18 +746,22 @@ public class MonitorSnippets implements Snippets { args.addConst("lockDepth", monitorenterNode.getMonitorId().getLockDepth()); args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("stackPointerRegister", registers.getStackPointerRegister()); - args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph.method())); + args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph)); + args.addConst("options", graph.getOptions()); + args.addConst("counters", counters); } else { args = new Arguments(monitorenterStub, graph.getGuardsStage(), tool.getLoweringStage()); args.add("object", monitorenterNode.object()); args.addConst("lockDepth", monitorenterNode.getMonitorId().getLockDepth()); - args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph.method())); + args.addConst("trace", isTracingEnabledForType(monitorenterNode.object()) || isTracingEnabledForMethod(graph)); + args.addConst("options", graph.getOptions()); + args.addConst("counters", counters); } - template(args).instantiate(providers.getMetaAccess(), monitorenterNode, DEFAULT_REPLACER, args); + template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), monitorenterNode, DEFAULT_REPLACER, args); } - public void lower(MonitorExitNode monitorexitNode, LoweringTool tool) { + public void lower(MonitorExitNode monitorexitNode, HotSpotRegistersProvider registers, LoweringTool tool) { StructuredGraph graph = monitorexitNode.graph(); Arguments args; @@ -581,14 +772,17 @@ public class MonitorSnippets implements Snippets { } args.add("object", monitorexitNode.object()); args.addConst("lockDepth", monitorexitNode.getMonitorId().getLockDepth()); - args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(graph.method())); + args.addConst("threadRegister", registers.getThreadRegister()); + args.addConst("trace", isTracingEnabledForType(monitorexitNode.object()) || isTracingEnabledForMethod(graph)); + args.addConst("options", graph.getOptions()); + args.addConst("counters", counters); - template(args).instantiate(providers.getMetaAccess(), monitorexitNode, DEFAULT_REPLACER, args); + template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), monitorexitNode, DEFAULT_REPLACER, args); } public static boolean isTracingEnabledForType(ValueNode object) { ResolvedJavaType type = StampTool.typeOrNull(object.stamp()); - String filter = TraceMonitorsTypeFilter.getValue(); + String filter = TraceMonitorsTypeFilter.getValue(object.getOptions()); if (filter == null) { return false; } else { @@ -602,18 +796,18 @@ public class MonitorSnippets implements Snippets { } } - public static boolean isTracingEnabledForMethod(ResolvedJavaMethod method) { - String filter = TraceMonitorsMethodFilter.getValue(); + public static boolean isTracingEnabledForMethod(StructuredGraph graph) { + String filter = TraceMonitorsMethodFilter.getValue(graph.getOptions()); if (filter == null) { return false; } else { if (filter.length() == 0) { return true; } - if (method == null) { + if (graph.method() == null) { return false; } - return (method.format("%H.%n").contains(filter)); + return (graph.method().format("%H.%n").contains(filter)); } } @@ -622,7 +816,7 @@ public class MonitorSnippets implements Snippets { * return points of the graph to initialize and check the monitor counter respectively. */ private void checkBalancedMonitors(StructuredGraph graph, LoweringTool tool) { - if (VERIFY_BALANCED_MONITORS) { + if (VerifyBalancedMonitors.getValue(options)) { NodeIterable nodes = graph.getNodes().filter(MonitorCounterNode.class); if (nodes.isEmpty()) { // Only insert the nodes if this is the first monitorenter being lowered. @@ -634,7 +828,7 @@ public class MonitorSnippets implements Snippets { graph.addAfterFixed(graph.start(), invoke); StructuredGraph inlineeGraph = providers.getReplacements().getSnippet(initCounter.getMethod(), null); - InliningUtil.inline(invoke, inlineeGraph, false, null, null); + InliningUtil.inline(invoke, inlineeGraph, false, null); List rets = graph.getNodes(ReturnNode.TYPE).snapshot(); for (ReturnNode ret : rets) { @@ -651,8 +845,8 @@ public class MonitorSnippets implements Snippets { Arguments args = new Arguments(checkCounter, graph.getGuardsStage(), tool.getLoweringStage()); args.addConst("errMsg", msg); - inlineeGraph = template(args).copySpecializedGraph(); - InliningUtil.inline(invoke, inlineeGraph, false, null, null); + inlineeGraph = template(graph.getDebug(), args).copySpecializedGraph(graph.getDebug()); + InliningUtil.inline(invoke, inlineeGraph, false, null); } } } @@ -667,31 +861,4 @@ public class MonitorSnippets implements Snippets { @NodeIntrinsic(ForeignCallNode.class) public static native void monitorexitStubC(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object, Word lock); - - /** - * Counters for the various paths for acquiring a lock. The counters whose names start with - * {@code "lock"} are mutually exclusive. The other counters are for paths that may be shared. - */ - public static final SnippetCounter.Group lockCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("MonitorEnters") : null; - public static final SnippetCounter lockBiasExisting = new SnippetCounter(lockCounters, "lock{bias:existing}", "bias-locked previously biased object"); - public static final SnippetCounter lockBiasAcquired = new SnippetCounter(lockCounters, "lock{bias:acquired}", "bias-locked newly biased object"); - public static final SnippetCounter lockBiasTransfer = new SnippetCounter(lockCounters, "lock{bias:transfer}", "bias-locked, biased transferred"); - public static final SnippetCounter lockCas = new SnippetCounter(lockCounters, "lock{cas}", "cas-locked an object"); - public static final SnippetCounter lockCasRecursive = new SnippetCounter(lockCounters, "lock{cas:recursive}", "cas-locked, recursive"); - public static final SnippetCounter lockStubEpochExpired = new SnippetCounter(lockCounters, "lock{stub:epoch-expired}", "stub-locked, epoch expired"); - public static final SnippetCounter lockStubRevoke = new SnippetCounter(lockCounters, "lock{stub:revoke}", "stub-locked, biased revoked"); - public static final SnippetCounter lockStubFailedCas = new SnippetCounter(lockCounters, "lock{stub:failed-cas}", "stub-locked, failed cas"); - - public static final SnippetCounter unbiasable = new SnippetCounter(lockCounters, "unbiasable", "object with unbiasable type"); - public static final SnippetCounter revokeBias = new SnippetCounter(lockCounters, "revokeBias", "object had bias revoked"); - - /** - * Counters for the various paths for releasing a lock. The counters whose names start with - * {@code "unlock"} are mutually exclusive. The other counters are for paths that may be shared. - */ - public static final SnippetCounter.Group unlockCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("MonitorExits") : null; - public static final SnippetCounter unlockBias = new SnippetCounter(unlockCounters, "unlock{bias}", "bias-unlocked an object"); - public static final SnippetCounter unlockCas = new SnippetCounter(unlockCounters, "unlock{cas}", "cas-unlocked an object"); - public static final SnippetCounter unlockCasRecursive = new SnippetCounter(unlockCounters, "unlock{cas:recursive}", "cas-unlocked an object, recursive"); - public static final SnippetCounter unlockStub = new SnippetCounter(unlockCounters, "unlock{stub}", "stub-unlocked an object"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java index 564e89a36f1..b5d78318876 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java @@ -22,8 +22,9 @@ */ package org.graalvm.compiler.hotspot.replacements; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static jdk.vm.ci.hotspot.HotSpotMetaAccessProvider.computeArrayAllocationSize; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; import static org.graalvm.compiler.core.common.calc.UnsignedMath.belowThan; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.CLASS_ARRAY_KLASS_LOCATION; @@ -53,8 +54,10 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOop; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeTlabTop; -import static org.graalvm.compiler.nodes.PiArrayNode.piArrayCast; -import static org.graalvm.compiler.nodes.PiNode.piCast; +import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileAllocations; +import static org.graalvm.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileAllocationsContext; +import static org.graalvm.compiler.nodes.PiArrayNode.piArrayCastToSnippetReplaceeStamp; +import static org.graalvm.compiler.nodes.PiNode.piCastToSnippetReplaceeStamp; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FREQUENT_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; @@ -64,17 +67,14 @@ import static org.graalvm.compiler.replacements.ReplacementsUtil.staticAssert; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring; import static org.graalvm.compiler.replacements.nodes.ExplodeLoopNode.explodeLoop; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; -import static jdk.vm.ci.hotspot.HotSpotMetaAccessProvider.computeArrayAllocationSize; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.StampFactory; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; @@ -86,17 +86,16 @@ import org.graalvm.compiler.hotspot.nodes.DimensionsNode; import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyFixedNode; import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode; import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; -import org.graalvm.compiler.hotspot.replacements.aot.ResolveConstantSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.DeoptimizeNode; -import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.PrefetchAllocateNode; +import org.graalvm.compiler.nodes.SnippetAnchorNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.debug.DynamicCounterNode; import org.graalvm.compiler.nodes.debug.VerifyHeapNode; -import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.extended.MembarNode; import org.graalvm.compiler.nodes.java.DynamicNewArrayNode; @@ -107,8 +106,10 @@ import org.graalvm.compiler.nodes.java.NewMultiArrayNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.ReplacementsUtil; import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -116,6 +117,8 @@ import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode; import org.graalvm.compiler.word.Word; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.code.MemoryBarriers; @@ -133,8 +136,6 @@ import jdk.vm.ci.meta.ResolvedJavaType; */ public class NewObjectSnippets implements Snippets { - public static final LocationIdentity INIT_LOCATION = NamedLocationIdentity.mutable("Initialization"); - enum ProfileContext { AllocatingMethod, InstanceOrArray, @@ -144,8 +145,8 @@ public class NewObjectSnippets implements Snippets { } @Fold - static String createName(String path, String typeContext) { - switch (HotspotSnippetsOptions.ProfileAllocationsContext.getValue()) { + static String createName(String path, String typeContext, OptionValues options) { + switch (ProfileAllocationsContext.getValue(options)) { case AllocatingMethod: return ""; case InstanceOrArray: @@ -161,21 +162,21 @@ public class NewObjectSnippets implements Snippets { } @Fold - static boolean doProfile() { - return HotspotSnippetsOptions.ProfileAllocations.getValue(); + static boolean doProfile(OptionValues options) { + return ProfileAllocations.getValue(options); } @Fold - static boolean withContext() { - ProfileContext context = HotspotSnippetsOptions.ProfileAllocationsContext.getValue(); + static boolean withContext(OptionValues options) { + ProfileContext context = ProfileAllocationsContext.getValue(options); return context == ProfileContext.AllocatingMethod || context == ProfileContext.AllocatedTypesInMethod; } - protected static void profileAllocation(String path, long size, String typeContext) { - if (doProfile()) { - String name = createName(path, typeContext); + protected static void profileAllocation(String path, long size, String typeContext, OptionValues options) { + if (doProfile(options)) { + String name = createName(path, typeContext, options); - boolean context = withContext(); + boolean context = withContext(options); DynamicCounterNode.counter(name, "number of bytes allocated", size, context); DynamicCounterNode.counter(name, "number of allocations", 1, context); } @@ -198,8 +199,14 @@ public class NewObjectSnippets implements Snippets { } @Snippet - public static Object allocateInstance(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, - @ConstantParameter boolean constantSize, @ConstantParameter String typeContext) { + public static Object allocateInstance(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents, + @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext, @ConstantParameter OptionValues options, + @ConstantParameter Counters counters) { + return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, hub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, options, counters)); + } + + public static Object allocateInstanceHelper(int size, KlassPointer hub, Word prototypeMarkWord, boolean fillContents, + Register threadRegister, boolean constantSize, String typeContext, OptionValues options, Counters counters) { Object result; Word thread = registerAsWord(threadRegister); Word top = readTlabTop(thread); @@ -208,39 +215,53 @@ public class NewObjectSnippets implements Snippets { if (useTLAB(INJECTED_VMCONFIG) && probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { writeTlabTop(thread, newTop); emitPrefetchAllocate(newTop, false); - result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, true); + result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, counters); } else { - new_stub.inc(); + if (counters != null && counters.stub != null) { + counters.stub.inc(); + } result = newInstance(HotSpotBackend.NEW_INSTANCE, hub); } - profileAllocation("instance", size, typeContext); - return piCast(verifyOop(result), StampFactory.forNodeIntrinsic()); + profileAllocation("instance", size, typeContext, options); + return verifyOop(result); } - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object newInstance(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub); @Snippet public static Object allocateInstancePIC(@ConstantParameter int size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents, - @ConstantParameter Register threadRegister, - @ConstantParameter boolean constantSize, @ConstantParameter String typeContext) { + @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext, @ConstantParameter OptionValues options, + @ConstantParameter Counters counters) { // Klass must be initialized by the time the first instance is allocated, therefore we can // just load it from the corresponding cell and avoid the resolution check. We have to use a // fixed load though, to prevent it from floating above the initialization. KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub); - return allocateInstance(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext); + return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, options, counters)); } @Snippet - public static Object allocateInstanceDynamic(Class type, Class classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister) { - if (probability(SLOW_PATH_PROBABILITY, type == null || DynamicNewInstanceNode.throwsInstantiationException(type, classClass))) { + public static Object allocateInstanceDynamic(Class type, Class classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { + if (probability(SLOW_PATH_PROBABILITY, type == null)) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + Class nonNullType = PiNode.piCastNonNullClass(type, SnippetAnchorNode.anchor()); + + if (probability(SLOW_PATH_PROBABILITY, DynamicNewInstanceNode.throwsInstantiationException(type, classClass))) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - KlassPointer hub = ClassGetHubNode.readClass(type); + return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, threadRegister, options, counters, nonNullType)); + } + + private static Object allocateInstanceDynamicHelper(Class type, boolean fillContents, Register threadRegister, OptionValues options, Counters counters, Class nonNullType) { + KlassPointer hub = ClassGetHubNode.readClass(nonNullType); if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) { - if (probability(FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(hub))) { - int layoutHelper = readLayoutHelper(hub); + KlassPointer nonNullHub = ClassGetHubNode.piCastNonNull(hub, SnippetAnchorNode.anchor()); + + if (probability(FAST_PATH_PROBABILITY, isInstanceKlassFullyInitialized(nonNullHub))) { + int layoutHelper = readLayoutHelper(nonNullHub); /* * src/share/vm/oops/klass.hpp: For instances, layout helper is a positive number, * the instance size. This size is already passed through align_object_size and @@ -248,12 +269,12 @@ public class NewObjectSnippets implements Snippets { * allocated using the fastpath. */ if (probability(FAST_PATH_PROBABILITY, (layoutHelper & 1) == 0)) { - Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); + Word prototypeMarkWord = nonNullHub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); /* * FIXME(je,ds): we should actually pass typeContext instead of "" but late * binding of parameters is not yet supported by the GraphBuilderPlugin system. */ - return allocateInstance(layoutHelper, hub, prototypeMarkWord, fillContents, threadRegister, false, ""); + return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", options, counters); } } } @@ -267,28 +288,32 @@ public class NewObjectSnippets implements Snippets { @Snippet public static Object allocatePrimitiveArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext) { + @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { + // Primitive array types are eagerly pre-resolved. We can use a floating load. KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub); - return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false); + return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters); } @Snippet public static Object allocateArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext) { - KlassPointer picHub = ResolveConstantSnippets.resolveKlassConstant(hub); - return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false); + @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { + // Array type would be resolved by dominating resolution. + KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub); + return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters); } @Snippet public static Object allocateArray(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext) { - Object result = allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false); - return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); + @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + @ConstantParameter OptionValues options, @ConstantParameter Counters counters) { + Object result = allocateArrayImpl(hub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, false, options, counters); + return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length); } - private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, - @ConstantParameter Register threadRegister, - @ConstantParameter boolean maybeUnroll, String typeContext, boolean skipNegativeCheck) { + private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, Register threadRegister, + boolean maybeUnroll, String typeContext, boolean skipNegativeCheck, OptionValues options, Counters counters) { Object result; int alignment = wordSize(); int allocationSize = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); @@ -300,40 +325,43 @@ public class NewObjectSnippets implements Snippets { probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) { writeTlabTop(thread, newTop); emitPrefetchAllocate(newTop, true); - newarray_loopInit.inc(); - result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, true); + if (counters != null && counters.arrayLoopInit != null) { + counters.arrayLoopInit.inc(); + } + result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, counters); } else { result = newArray(HotSpotBackend.NEW_ARRAY, hub, length, fillContents); } - profileAllocation("array", allocationSize, typeContext); + profileAllocation("array", allocationSize, typeContext, options); return result; } - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object newArray(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int length, boolean fillContents); public static final ForeignCallDescriptor DYNAMIC_NEW_ARRAY = new ForeignCallDescriptor("dynamic_new_array", Object.class, Class.class, int.class); public static final ForeignCallDescriptor DYNAMIC_NEW_INSTANCE = new ForeignCallDescriptor("dynamic_new_instance", Object.class, Class.class); - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object dynamicNewArrayStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class elementType, int length); public static Object dynamicNewInstanceStub(Class elementType) { return dynamicNewInstanceStubCall(DYNAMIC_NEW_INSTANCE, elementType); } - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object dynamicNewInstanceStubCall(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class elementType); @Snippet public static Object allocateArrayDynamic(Class elementType, Class voidClass, int length, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, - @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord) { - Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind, knownLayoutHelper, prototypeMarkWord); + @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord, @ConstantParameter OptionValues options, + @ConstantParameter Counters counters) { + Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind, knownLayoutHelper, prototypeMarkWord, options, counters); return result; } private static Object allocateArrayDynamicImpl(Class elementType, Class voidClass, int length, boolean fillContents, Register threadRegister, JavaKind knownElementKind, - int knownLayoutHelper, Word prototypeMarkWord) { + int knownLayoutHelper, Word prototypeMarkWord, OptionValues options, Counters counters) { /* * We only need the dynamic check for void when we have no static information from * knownElementKind. @@ -344,10 +372,15 @@ public class NewObjectSnippets implements Snippets { } KlassPointer klass = loadKlassFromObject(elementType, arrayKlassOffset(INJECTED_VMCONFIG), CLASS_ARRAY_KLASS_LOCATION); - if (probability(BranchProbabilityNode.NOT_FREQUENT_PROBABILITY, klass.isNull() || length < 0)) { + if (klass.isNull()) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - int layoutHelper = knownElementKind != JavaKind.Illegal ? knownLayoutHelper : readLayoutHelper(klass); + KlassPointer nonNullKlass = ClassGetHubNode.piCastNonNull(klass, SnippetAnchorNode.anchor()); + + if (length < 0) { + DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); + } + int layoutHelper = knownElementKind != JavaKind.Illegal ? knownLayoutHelper : readLayoutHelper(nonNullKlass); //@formatter:off // from src/share/vm/oops/klass.hpp: // @@ -364,8 +397,8 @@ public class NewObjectSnippets implements Snippets { int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG); - Object result = allocateArrayImpl(klass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", true); - return piArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); + Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", true, options, counters); + return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length); } /** @@ -376,18 +409,19 @@ public class NewObjectSnippets implements Snippets { Word dims = DimensionsNode.allocaDimsArray(rank); ExplodeLoopNode.explodeLoop(); for (int i = 0; i < rank; i++) { - dims.writeInt(i * 4, dimensions[i], INIT_LOCATION); + dims.writeInt(i * 4, dimensions[i], LocationIdentity.init()); } return newArrayCall(HotSpotBackend.NEW_MULTI_ARRAY, hub, rank, dims); } @Snippet public static Object newmultiarrayPIC(KlassPointer hub, @ConstantParameter int rank, @VarargsParameter int[] dimensions) { - KlassPointer hubPIC = ResolveConstantSnippets.resolveKlassConstant(hub); - return newmultiarray(hubPIC, rank, dimensions); + // Array type would be resolved by dominating resolution. + KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub); + return newmultiarray(picHub, rank, dimensions); } - @NodeIntrinsic(value = ForeignCallNode.class, returnStampIsNonNull = true) + @NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true) public static native Object newArrayCall(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int rank, Word dims); /** @@ -406,15 +440,15 @@ public class NewObjectSnippets implements Snippets { * @param startOffset offset to begin zeroing. May not be word aligned. * @param manualUnroll maximally unroll zeroing */ - private static void zeroMemory(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, boolean useSnippetCounters) { - fillMemory(0, size, memory, constantSize, startOffset, manualUnroll, useSnippetCounters); + private static void zeroMemory(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { + fillMemory(0, size, memory, constantSize, startOffset, manualUnroll, counters); } - private static void fillMemory(long value, int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, boolean useSnippetCounters) { + private static void fillMemory(long value, int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { ReplacementsUtil.runtimeAssert((size & 0x7) == 0, "unaligned object size"); int offset = startOffset; if ((offset & 0x7) != 0) { - memory.writeInt(offset, (int) value, INIT_LOCATION); + memory.writeInt(offset, (int) value, LocationIdentity.init()); offset += 4; } ReplacementsUtil.runtimeAssert((offset & 0x7) == 0, "unaligned offset"); @@ -423,31 +457,32 @@ public class NewObjectSnippets implements Snippets { // This case handles arrays of constant length. Instead of having a snippet variant for // each length, generate a chain of stores of maximum length. Once it's inlined the // break statement will trim excess stores. - if (useSnippetCounters) { - new_seqInit.inc(); + if (counters != null && counters.instanceSeqInit != null) { + counters.instanceSeqInit.inc(); } + explodeLoop(); for (int i = 0; i < MAX_UNROLLED_OBJECT_ZEROING_STORES; i++, offset += 8) { if (offset == size) { break; } - memory.initializeLong(offset, value, INIT_LOCATION); + memory.initializeLong(offset, value, LocationIdentity.init()); } } else { // Use Word instead of int to avoid extension to long in generated code - Word off = Word.signed(offset); + Word off = WordFactory.signed(offset); if (constantSize && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) { - if (useSnippetCounters) { - new_seqInit.inc(); + if (counters != null && counters.instanceSeqInit != null) { + counters.instanceSeqInit.inc(); } explodeLoop(); } else { - if (useSnippetCounters) { - new_loopInit.inc(); + if (counters != null && counters.instanceLoopInit != null) { + counters.instanceLoopInit.inc(); } } for (; off.rawValue() < size; off = off.add(8)) { - memory.initializeLong(off, value, INIT_LOCATION); + memory.initializeLong(off, value, LocationIdentity.init()); } } } @@ -462,8 +497,8 @@ public class NewObjectSnippets implements Snippets { * @param startOffset offset to begin zeroing. May not be word aligned. * @param manualUnroll maximally unroll zeroing */ - private static void fillWithGarbage(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, boolean useSnippetCounters) { - fillMemory(0xfefefefefefefefeL, size, memory, constantSize, startOffset, manualUnroll, useSnippetCounters); + private static void fillWithGarbage(int size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { + fillMemory(0xfefefefefefefefeL, size, memory, constantSize, startOffset, manualUnroll, counters); } /** @@ -471,31 +506,31 @@ public class NewObjectSnippets implements Snippets { * since they can't be compiled in stubs. */ public static Object formatObjectForStub(KlassPointer hub, int size, Word memory, Word compileTimePrototypeMarkWord) { - return formatObject(hub, size, memory, compileTimePrototypeMarkWord, true, false, false); + return formatObject(hub, size, memory, compileTimePrototypeMarkWord, true, false, null); } /** * Formats some allocated memory with an object header and zeroes out the rest. */ - protected static Object formatObject(KlassPointer hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, boolean useSnippetCounters) { + protected static Object formatObject(KlassPointer hub, int size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, Counters counters) { Word prototypeMarkWord = useBiasedLocking(INJECTED_VMCONFIG) ? hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord; initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { - zeroMemory(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, useSnippetCounters); + zeroMemory(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters); } else if (REPLACEMENTS_ASSERTIONS_ENABLED) { - fillWithGarbage(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, useSnippetCounters); + fillWithGarbage(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters); } - MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, INIT_LOCATION); - return memory.toObject(); + MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init()); + return memory.toObjectNonNull(); } @Snippet protected static void verifyHeap(@ConstantParameter Register threadRegister) { Word thread = registerAsWord(threadRegister); Word topValue = readTlabTop(thread); - if (!topValue.equal(Word.zero())) { + if (!topValue.equal(WordFactory.zero())) { Word topValueContents = topValue.readWord(0, MARK_WORD_LOCATION); - if (topValueContents.equal(Word.zero())) { + if (topValueContents.equal(WordFactory.zero())) { AssertionSnippets.vmMessageC(AssertionSnippets.ASSERTION_VM_MESSAGE_C, true, cstring("overzeroing of TLAB detected"), 0L, 0L, 0L); } } @@ -505,43 +540,62 @@ public class NewObjectSnippets implements Snippets { * Formats some allocated memory with an object header and zeroes out the rest. */ public static Object formatArray(KlassPointer hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents, boolean maybeUnroll, - boolean useSnippetCounters) { - memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, INIT_LOCATION); + Counters counters) { + memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, LocationIdentity.init()); /* * store hub last as the concurrent garbage collectors assume length is valid if hub field * is not null */ initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { - zeroMemory(allocationSize, memory, false, headerSize, maybeUnroll, useSnippetCounters); + zeroMemory(allocationSize, memory, false, headerSize, maybeUnroll, counters); } else if (REPLACEMENTS_ASSERTIONS_ENABLED) { - fillWithGarbage(allocationSize, memory, false, headerSize, maybeUnroll, useSnippetCounters); + fillWithGarbage(allocationSize, memory, false, headerSize, maybeUnroll, counters); } - MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, INIT_LOCATION); - return memory.toObject(); + MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init()); + return memory.toObjectNonNull(); + } + + static class Counters { + Counters(SnippetCounter.Group.Factory factory) { + Group newInstance = factory.createSnippetCounterGroup("NewInstance"); + Group newArray = factory.createSnippetCounterGroup("NewArray"); + instanceSeqInit = new SnippetCounter(newInstance, "tlabSeqInit", "TLAB alloc with unrolled zeroing"); + instanceLoopInit = new SnippetCounter(newInstance, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); + arrayLoopInit = new SnippetCounter(newArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); + stub = new SnippetCounter(newInstance, "stub", "alloc and zeroing via stub"); + } + + final SnippetCounter instanceSeqInit; + final SnippetCounter instanceLoopInit; + final SnippetCounter arrayLoopInit; + final SnippetCounter stub; } public static class Templates extends AbstractTemplates { - private final SnippetInfo allocateInstance = snippet(NewObjectSnippets.class, "allocateInstance", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateInstancePIC = snippet(NewObjectSnippets.class, "allocateInstancePIC", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, + private final SnippetInfo allocateInstance = snippet(NewObjectSnippets.class, "allocateInstance", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo allocateInstancePIC = snippet(NewObjectSnippets.class, "allocateInstancePIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateArray = snippet(NewObjectSnippets.class, "allocateArray", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateArrayPIC = snippet(NewObjectSnippets.class, "allocateArrayPIC", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocatePrimitiveArrayPIC = snippet(NewObjectSnippets.class, "allocatePrimitiveArrayPIC", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, + private final SnippetInfo allocateArray = snippet(NewObjectSnippets.class, "allocateArray", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo allocateArrayPIC = snippet(NewObjectSnippets.class, "allocateArrayPIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo allocatePrimitiveArrayPIC = snippet(NewObjectSnippets.class, "allocatePrimitiveArrayPIC", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateArrayDynamic = snippet(NewObjectSnippets.class, "allocateArrayDynamic", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, + private final SnippetInfo allocateArrayDynamic = snippet(NewObjectSnippets.class, "allocateArrayDynamic", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo allocateInstanceDynamic = snippet(NewObjectSnippets.class, "allocateInstanceDynamic", INIT_LOCATION, MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, + private final SnippetInfo allocateInstanceDynamic = snippet(NewObjectSnippets.class, "allocateInstanceDynamic", MARK_WORD_LOCATION, HUB_WRITE_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray", INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); - private final SnippetInfo newmultiarrayPIC = snippet(NewObjectSnippets.class, "newmultiarrayPIC", INIT_LOCATION, TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo newmultiarray = snippet(NewObjectSnippets.class, "newmultiarray", TLAB_TOP_LOCATION, TLAB_END_LOCATION); + private final SnippetInfo newmultiarrayPIC = snippet(NewObjectSnippets.class, "newmultiarrayPIC", TLAB_TOP_LOCATION, TLAB_END_LOCATION); private final SnippetInfo verifyHeap = snippet(NewObjectSnippets.class, "verifyHeap"); private final GraalHotSpotVMConfig config; + private final Counters counters; - public Templates(HotSpotProviders providers, TargetDescription target, GraalHotSpotVMConfig config) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, + GraalHotSpotVMConfig config) { + super(options, factories, providers, providers.getSnippetReflection(), target); this.config = config; + counters = new Counters(factory); } /** @@ -554,7 +608,8 @@ public class NewObjectSnippets implements Snippets { ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), type.klass(), providers.getMetaAccess(), graph); int size = instanceSize(type); - SnippetInfo snippet = GeneratePIC.getValue() ? allocateInstancePIC : allocateInstance; + OptionValues localOptions = graph.getOptions(); + SnippetInfo snippet = GeneratePIC.getValue(localOptions) ? allocateInstancePIC : allocateInstance; Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); args.addConst("size", size); args.add("hub", hub); @@ -562,10 +617,12 @@ public class NewObjectSnippets implements Snippets { args.addConst("fillContents", newInstanceNode.fillContents()); args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("constantSize", true); - args.addConst("typeContext", HotspotSnippetsOptions.ProfileAllocations.getValue() ? type.toJavaName(false) : ""); + args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? type.toJavaName(false) : ""); + args.addConst("options", localOptions); + args.addConst("counters", counters); - SnippetTemplate template = template(args); - Debug.log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args); + SnippetTemplate template = template(graph.getDebug(), args); + graph.getDebug().log("Lowering allocateInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, args); template.instantiate(providers.getMetaAccess(), newInstanceNode, DEFAULT_REPLACER, args); } @@ -581,8 +638,9 @@ public class NewObjectSnippets implements Snippets { final int headerSize = getArrayBaseOffset(elementKind); int log2ElementSize = CodeUtil.log2(HotSpotJVMCIRuntimeProvider.getArrayIndexScale(elementKind)); + OptionValues localOptions = graph.getOptions(); SnippetInfo snippet; - if (GeneratePIC.getValue()) { + if (GeneratePIC.getValue(localOptions)) { if (elementType.isPrimitive()) { snippet = allocatePrimitiveArrayPIC; } else { @@ -603,27 +661,33 @@ public class NewObjectSnippets implements Snippets { args.addConst("fillContents", newArrayNode.fillContents()); args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("maybeUnroll", length.isConstant()); - args.addConst("typeContext", HotspotSnippetsOptions.ProfileAllocations.getValue() ? arrayType.toJavaName(false) : ""); - SnippetTemplate template = template(args); - Debug.log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); + args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? arrayType.toJavaName(false) : ""); + args.addConst("options", localOptions); + args.addConst("counters", counters); + SnippetTemplate template = template(graph.getDebug(), args); + graph.getDebug().log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args); } public void lower(DynamicNewInstanceNode newInstanceNode, HotSpotRegistersProvider registers, LoweringTool tool) { Arguments args = new Arguments(allocateInstanceDynamic, newInstanceNode.graph().getGuardsStage(), tool.getLoweringStage()); + OptionValues localOptions = newInstanceNode.getOptions(); args.add("type", newInstanceNode.getInstanceType()); ValueNode classClass = newInstanceNode.getClassClass(); assert classClass != null; args.add("classClass", classClass); args.addConst("fillContents", newInstanceNode.fillContents()); args.addConst("threadRegister", registers.getThreadRegister()); + args.addConst("options", localOptions); + args.addConst("counters", counters); - SnippetTemplate template = template(args); + SnippetTemplate template = template(newInstanceNode.getDebug(), args); template.instantiate(providers.getMetaAccess(), newInstanceNode, DEFAULT_REPLACER, args); } public void lower(DynamicNewArrayNode newArrayNode, HotSpotRegistersProvider registers, LoweringTool tool) { StructuredGraph graph = newArrayNode.graph(); + OptionValues localOptions = graph.getOptions(); Arguments args = new Arguments(allocateArrayDynamic, newArrayNode.graph().getGuardsStage(), tool.getLoweringStage()); args.add("elementType", newArrayNode.getElementType()); ValueNode voidClass = newArrayNode.getVoidClass(); @@ -644,7 +708,9 @@ public class NewObjectSnippets implements Snippets { args.addConst("knownLayoutHelper", 0); } args.add("prototypeMarkWord", lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord()); - SnippetTemplate template = template(args); + args.addConst("options", localOptions); + args.addConst("counters", counters); + SnippetTemplate template = template(graph.getDebug(), args); template.instantiate(providers.getMetaAccess(), newArrayNode, DEFAULT_REPLACER, args); } @@ -654,6 +720,7 @@ public class NewObjectSnippets implements Snippets { public void lower(NewMultiArrayNode newmultiarrayNode, LoweringTool tool) { StructuredGraph graph = newmultiarrayNode.graph(); + OptionValues localOptions = graph.getOptions(); int rank = newmultiarrayNode.dimensionCount(); ValueNode[] dims = new ValueNode[rank]; for (int i = 0; i < newmultiarrayNode.dimensionCount(); i++) { @@ -662,12 +729,12 @@ public class NewObjectSnippets implements Snippets { HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) newmultiarrayNode.type(); ConstantNode hub = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), type.klass(), providers.getMetaAccess(), graph); - SnippetInfo snippet = GeneratePIC.getValue() ? newmultiarrayPIC : newmultiarray; + SnippetInfo snippet = GeneratePIC.getValue(localOptions) ? newmultiarrayPIC : newmultiarray; Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); args.add("hub", hub); args.addConst("rank", rank); args.addVarargs("dimensions", int.class, StampFactory.forKind(JavaKind.Int), dims); - template(args).instantiate(providers.getMetaAccess(), newmultiarrayNode, DEFAULT_REPLACER, args); + template(newmultiarrayNode.getDebug(), args).instantiate(providers.getMetaAccess(), newmultiarrayNode, DEFAULT_REPLACER, args); } private static int instanceSize(HotSpotResolvedObjectType type) { @@ -681,20 +748,11 @@ public class NewObjectSnippets implements Snippets { Arguments args = new Arguments(verifyHeap, verifyHeapNode.graph().getGuardsStage(), tool.getLoweringStage()); args.addConst("threadRegister", registers.getThreadRegister()); - SnippetTemplate template = template(args); + SnippetTemplate template = template(verifyHeapNode.getDebug(), args); template.instantiate(providers.getMetaAccess(), verifyHeapNode, DEFAULT_REPLACER, args); } else { GraphUtil.removeFixedWithUnusedInputs(verifyHeapNode); } } } - - private static final SnippetCounter.Group countersNew = SnippetCounters.getValue() ? new SnippetCounter.Group("NewInstance") : null; - private static final SnippetCounter new_seqInit = new SnippetCounter(countersNew, "tlabSeqInit", "TLAB alloc with unrolled zeroing"); - private static final SnippetCounter new_loopInit = new SnippetCounter(countersNew, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); - private static final SnippetCounter new_stub = new SnippetCounter(countersNew, "stub", "alloc and zeroing via stub"); - - private static final SnippetCounter.Group countersNewArray = SnippetCounters.getValue() ? new SnippetCounter.Group("NewArray") : null; - private static final SnippetCounter newarray_loopInit = new SnippetCounter(countersNewArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); - private static final SnippetCounter newarray_stub = new SnippetCounter(countersNewArray, "stub", "alloc and zeroing via stub"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java index 7e6252df6d3..b12cf66155f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectCloneNode.java @@ -22,13 +22,12 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.CompilationIdentifier.INVALID_COMPILATION_ID; - import java.lang.reflect.Method; +import org.graalvm.compiler.core.common.type.AbstractPointerStamp; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampPair; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind; @@ -61,6 +60,18 @@ public final class ObjectCloneNode extends BasicObjectCloneNode implements Virtu super(TYPE, invokeKind, targetMethod, bci, returnStamp, receiver); } + @Override + protected Stamp computeStamp(ValueNode object) { + if (getConcreteType(object.stamp()) != null) { + return AbstractPointerStamp.pointerNonNull(object.stamp()); + } + /* + * If this call can't be intrinsified don't report a non-null stamp, otherwise the stamp + * would change when this is lowered back to an invoke and we might lose a null check. + */ + return AbstractPointerStamp.pointerMaybeNull(object.stamp()); + } + @Override @SuppressWarnings("try") protected StructuredGraph getLoweredSnippetGraph(LoweringTool tool) { @@ -72,21 +83,23 @@ public final class ObjectCloneNode extends BasicObjectCloneNode implements Virtu final ResolvedJavaMethod snippetMethod = tool.getMetaAccess().lookupJavaMethod(method); final Replacements replacements = tool.getReplacements(); StructuredGraph snippetGraph = null; - try (Scope s = Debug.scope("ArrayCloneSnippet", snippetMethod)) { + DebugContext debug = getDebug(); + try (DebugContext.Scope s = debug.scope("ArrayCloneSnippet", snippetMethod)) { snippetGraph = replacements.getSnippet(snippetMethod, null); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } assert snippetGraph != null : "ObjectCloneSnippets should be installed"; - return lowerReplacement((StructuredGraph) snippetGraph.copy(), tool); + assert getConcreteType(stamp()) != null; + return lowerReplacement((StructuredGraph) snippetGraph.copy(getDebug()), tool); } assert false : "unhandled array type " + type.getComponentType().getJavaKind(); } else { Assumptions assumptions = graph().getAssumptions(); type = getConcreteType(getObject().stamp()); if (type != null) { - StructuredGraph newGraph = new StructuredGraph(AllowAssumptions.from(assumptions != null), INVALID_COMPILATION_ID); + StructuredGraph newGraph = new StructuredGraph.Builder(graph().getOptions(), graph().getDebug(), AllowAssumptions.ifNonNull(assumptions)).build(); ParameterNode param = newGraph.addWithoutUnique(new ParameterNode(0, StampPair.createSingle(getObject().stamp()))); NewInstanceNode newInstance = newGraph.add(new NewInstanceNode(type, true)); newGraph.addAfterFixed(newGraph.start(), newInstance); @@ -98,10 +111,12 @@ public final class ObjectCloneNode extends BasicObjectCloneNode implements Virtu newGraph.addBeforeFixed(returnNode, load); newGraph.addBeforeFixed(returnNode, newGraph.add(new StoreFieldNode(newInstance, field, load))); } + assert getConcreteType(stamp()) != null; return lowerReplacement(newGraph, tool); } } } + assert getConcreteType(stamp()) == null; return null; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ReflectionGetCallerClassNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ReflectionGetCallerClassNode.java index 6556bd91064..fe6ef1fc232 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ReflectionGetCallerClassNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ReflectionGetCallerClassNode.java @@ -22,9 +22,6 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_UNKNOWN; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_20; - import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; @@ -47,7 +44,7 @@ import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; -@NodeInfo(cycles = CYCLES_UNKNOWN, cyclesRationale = "This node can be lowered to a call", size = SIZE_20) +@NodeInfo public final class ReflectionGetCallerClassNode extends MacroStateSplitNode implements Canonicalizable, Lowerable { public static final NodeClass TYPE = NodeClass.create(ReflectionGetCallerClassNode.class); @@ -80,7 +77,7 @@ public final class ReflectionGetCallerClassNode extends MacroStateSplitNode impl /** * If inlining is deep enough this method returns a {@link ConstantNode} of the caller class by - * walking the the stack. + * walking the stack. * * @param metaAccess * @return ConstantNode of the caller class, or null diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java index b72577f8a5a..43eedc6669b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java @@ -22,18 +22,19 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.PiNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.word.Word; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.WordFactory; import jdk.vm.ci.meta.JavaKind; @@ -62,9 +63,9 @@ public class SHA2Substitutions { @MethodSubstitution(isStatic = false) static void implCompress0(Object receiver, byte[] buf, int ofs) { Object realReceiver = PiNode.piCastNonNull(receiver, shaClass); - Object state = UnsafeLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); - Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); - Word stateAddr = Word.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); + Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); + Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); + Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); HotSpotBackend.sha2ImplCompressStub(bufAddr, stateAddr); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java index 0abda014a92..95ecd5b55d7 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java @@ -22,18 +22,19 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.PiNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.word.Word; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.WordFactory; import jdk.vm.ci.meta.JavaKind; @@ -62,9 +63,9 @@ public class SHA5Substitutions { @MethodSubstitution(isStatic = false) static void implCompress0(Object receiver, byte[] buf, int ofs) { Object realReceiver = PiNode.piCastNonNull(receiver, shaClass); - Object state = UnsafeLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); - Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); - Word stateAddr = Word.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); + Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); + Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); + Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); HotSpotBackend.sha5ImplCompressStub(bufAddr, stateAddr); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java index 7d389f087c2..18d101fb16c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java @@ -22,18 +22,19 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.util.Util.Java8OrEarlier; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; +import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier; import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitution; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; import org.graalvm.compiler.nodes.PiNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.word.Word; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.WordFactory; import jdk.vm.ci.meta.JavaKind; @@ -62,9 +63,9 @@ public class SHASubstitutions { @MethodSubstitution(isStatic = false) static void implCompress0(Object receiver, byte[] buf, int ofs) { Object realReceiver = PiNode.piCastNonNull(receiver, shaClass); - Object state = UnsafeLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); - Word bufAddr = Word.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); - Word stateAddr = Word.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); + Object state = RawLoadNode.load(realReceiver, stateOffset, JavaKind.Object, LocationIdentity.any()); + Word bufAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(buf, getArrayBaseOffset(JavaKind.Byte) + ofs)); + Word stateAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(state, getArrayBaseOffset(JavaKind.Int))); HotSpotBackend.shaImplCompressStub(bufAddr, stateAddr); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java index 434ae81a515..f6c9bb75826 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java @@ -28,12 +28,13 @@ import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.LocationIdentity; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.debug.StringToBytesNode; import org.graalvm.compiler.nodes.java.NewArrayNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -41,6 +42,7 @@ import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.replacements.nodes.CStringConstant; import org.graalvm.compiler.word.Word; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.JavaKind; @@ -73,15 +75,15 @@ public class StringToBytesSnippets implements Snippets { private final SnippetInfo create; - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); create = snippet(StringToBytesSnippets.class, "transform", NamedLocationIdentity.getArrayLocation(JavaKind.Byte)); } public void lower(StringToBytesNode stringToBytesNode, LoweringTool tool) { Arguments args = new Arguments(create, stringToBytesNode.graph().getGuardsStage(), tool.getLoweringStage()); args.addConst("compilationTimeString", stringToBytesNode.getValue()); - SnippetTemplate template = template(args); + SnippetTemplate template = template(stringToBytesNode.getDebug(), args); template.instantiate(providers.getMetaAccess(), stringToBytesNode, DEFAULT_REPLACER, args); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java index e80bb98c19d..bb720f1629e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java @@ -22,13 +22,13 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.LocationIdentity.any; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_OSTHREAD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_THREAD_OBJECT_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.osThreadInterruptedOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.osThreadOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.threadObjectOffset; +import static org.graalvm.word.LocationIdentity.any; import org.graalvm.compiler.api.replacements.ClassSubstitution; import org.graalvm.compiler.api.replacements.MethodSubstitution; @@ -45,6 +45,9 @@ import org.graalvm.compiler.word.Word; @ClassSubstitution(Thread.class) public class ThreadSubstitutions { + /** + * hidden in 9. + */ @MethodSubstitution(isStatic = false, optional = true) public static boolean isInterrupted(final Thread thisObject, boolean clearInterrupted) { Word javaThread = CurrentJavaThreadNode.get(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/TypeCheckSnippetUtils.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/TypeCheckSnippetUtils.java index b112d1ae3b9..47e256d50dd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/TypeCheckSnippetUtils.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/TypeCheckSnippetUtils.java @@ -22,7 +22,6 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.KLASS_SUPER_CHECK_OFFSET_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.METASPACE_ARRAY_LENGTH_LOCATION; @@ -47,6 +46,7 @@ import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.TypeCheckHints; import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.word.Word; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; @@ -59,44 +59,44 @@ import jdk.vm.ci.meta.MetaAccessProvider; */ public class TypeCheckSnippetUtils { - static boolean checkSecondarySubType(KlassPointer t, KlassPointer s) { + static boolean checkSecondarySubType(KlassPointer t, KlassPointer sNonNull, Counters counters) { // if (S.cache == T) return true - if (s.readKlassPointer(secondarySuperCacheOffset(INJECTED_VMCONFIG), SECONDARY_SUPER_CACHE_LOCATION).equal(t)) { - cacheHit.inc(); + if (sNonNull.readKlassPointer(secondarySuperCacheOffset(INJECTED_VMCONFIG), SECONDARY_SUPER_CACHE_LOCATION).equal(t)) { + counters.cacheHit.inc(); return true; } - return checkSelfAndSupers(t, s); + return checkSelfAndSupers(t, sNonNull, counters); } - static boolean checkUnknownSubType(KlassPointer t, KlassPointer s) { + static boolean checkUnknownSubType(KlassPointer t, KlassPointer sNonNull, Counters counters) { // int off = T.offset int superCheckOffset = t.readInt(superCheckOffsetOffset(INJECTED_VMCONFIG), KLASS_SUPER_CHECK_OFFSET_LOCATION); boolean primary = superCheckOffset != secondarySuperCacheOffset(INJECTED_VMCONFIG); // if (T = S[off]) return true - if (s.readKlassPointer(superCheckOffset, PRIMARY_SUPERS_LOCATION).equal(t)) { + if (sNonNull.readKlassPointer(superCheckOffset, PRIMARY_SUPERS_LOCATION).equal(t)) { if (primary) { - cacheHit.inc(); + counters.cacheHit.inc(); } else { - displayHit.inc(); + counters.displayHit.inc(); } return true; } // if (off != &cache) return false if (primary) { - displayMiss.inc(); + counters.displayMiss.inc(); return false; } - return checkSelfAndSupers(t, s); + return checkSelfAndSupers(t, sNonNull, counters); } - private static boolean checkSelfAndSupers(KlassPointer t, KlassPointer s) { + private static boolean checkSelfAndSupers(KlassPointer t, KlassPointer s, Counters counters) { // if (T == S) return true if (s.equal(t)) { - T_equals_S.inc(); + counters.equalsSecondary.inc(); return true; } @@ -106,14 +106,43 @@ public class TypeCheckSnippetUtils { for (int i = 0; i < length; i++) { if (probability(NOT_LIKELY_PROBABILITY, t.equal(loadSecondarySupersElement(secondarySupers, i)))) { s.writeKlassPointer(secondarySuperCacheOffset(INJECTED_VMCONFIG), t, SECONDARY_SUPER_CACHE_LOCATION); - secondariesHit.inc(); + counters.secondariesHit.inc(); return true; } } - secondariesMiss.inc(); + counters.secondariesMiss.inc(); return false; } + static class Counters { + final SnippetCounter hintsHit; + final SnippetCounter hintsMiss; + final SnippetCounter exactHit; + final SnippetCounter exactMiss; + final SnippetCounter isNull; + final SnippetCounter cacheHit; + final SnippetCounter secondariesHit; + final SnippetCounter secondariesMiss; + final SnippetCounter displayHit; + final SnippetCounter displayMiss; + final SnippetCounter equalsSecondary; + + Counters(SnippetCounter.Group.Factory factory) { + Group group = factory.createSnippetCounterGroup("TypeCheck"); + hintsHit = new SnippetCounter(group, "hintsHit", "hit a hint type"); + hintsMiss = new SnippetCounter(group, "hintsMiss", "missed a hint type"); + exactHit = new SnippetCounter(group, "exactHit", "exact type test succeeded"); + exactMiss = new SnippetCounter(group, "exactMiss", "exact type test failed"); + isNull = new SnippetCounter(group, "isNull", "object tested was null"); + cacheHit = new SnippetCounter(group, "cacheHit", "secondary type cache hit"); + secondariesHit = new SnippetCounter(group, "secondariesHit", "secondaries scan succeeded"); + secondariesMiss = new SnippetCounter(group, "secondariesMiss", "secondaries scan failed"); + displayHit = new SnippetCounter(group, "displayHit", "primary type test succeeded"); + displayMiss = new SnippetCounter(group, "displayMiss", "primary type test failed"); + equalsSecondary = new SnippetCounter(group, "T_equals_S", "object type was equal to secondary type"); + } + } + /** * A set of type check hints ordered by decreasing probabilities. */ @@ -158,18 +187,4 @@ public class TypeCheckSnippetUtils { static KlassPointer loadSecondarySupersElement(Word metaspaceArray, int index) { return KlassPointer.fromWord(metaspaceArray.readWord(metaspaceArrayBaseOffset(INJECTED_VMCONFIG) + index * wordSize(), SECONDARY_SUPERS_ELEMENT_LOCATION)); } - - private static final SnippetCounter.Group counters = SnippetCounters.getValue() ? new SnippetCounter.Group("TypeCheck") : null; - static final SnippetCounter hintsHit = new SnippetCounter(counters, "hintsHit", "hit a hint type"); - static final SnippetCounter hintsMiss = new SnippetCounter(counters, "hintsMiss", "missed a hint type"); - static final SnippetCounter exactHit = new SnippetCounter(counters, "exactHit", "exact type test succeeded"); - static final SnippetCounter exactMiss = new SnippetCounter(counters, "exactMiss", "exact type test failed"); - static final SnippetCounter isNull = new SnippetCounter(counters, "isNull", "object tested was null"); - static final SnippetCounter cacheHit = new SnippetCounter(counters, "cacheHit", "secondary type cache hit"); - static final SnippetCounter secondariesHit = new SnippetCounter(counters, "secondariesHit", "secondaries scan succeeded"); - static final SnippetCounter secondariesMiss = new SnippetCounter(counters, "secondariesMiss", "secondaries scan failed"); - static final SnippetCounter displayHit = new SnippetCounter(counters, "displayHit", "primary type test succeeded"); - static final SnippetCounter displayMiss = new SnippetCounter(counters, "displayMiss", "primary type test failed"); - static final SnippetCounter T_equals_S = new SnippetCounter(counters, "T_equals_S", "object type was equal to secondary type"); - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java index 0eef6871a4e..31d343bb950 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/UnsafeLoadSnippets.java @@ -26,11 +26,13 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.nodes.extended.FixedValueAnchorNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; @@ -55,15 +57,15 @@ public class UnsafeLoadSnippets implements Snippets { private final SnippetInfo unsafeLoad = snippet(UnsafeLoadSnippets.class, "lowerUnsafeLoad"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); } - public void lower(UnsafeLoadNode load, LoweringTool tool) { + public void lower(RawLoadNode load, LoweringTool tool) { Arguments args = new Arguments(unsafeLoad, load.graph().getGuardsStage(), tool.getLoweringStage()); args.add("object", load.object()); args.add("offset", load.offset()); - template(args).instantiate(providers.getMetaAccess(), load, DEFAULT_REPLACER, args); + template(load.getDebug(), args).instantiate(providers.getMetaAccess(), load, DEFAULT_REPLACER, args); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java index 526e9a572c9..b4cdc08ace8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.hotspot.replacements; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; +import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayBaseOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayIndexScale; @@ -43,19 +43,17 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.LIKELY_P import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; -import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; +import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.hotspot.CompressEncoding; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.meta.HotSpotRegistersProvider; -import org.graalvm.compiler.hotspot.nodes.CompressionNode; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePostWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1ArrayRangePreWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1PostWriteBarrier; @@ -63,9 +61,10 @@ import org.graalvm.compiler.hotspot.nodes.G1PreWriteBarrier; import org.graalvm.compiler.hotspot.nodes.G1ReferentFieldReadBarrier; import org.graalvm.compiler.hotspot.nodes.GetObjectAddressNode; import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode; +import org.graalvm.compiler.hotspot.nodes.HotSpotCompressionNode; import org.graalvm.compiler.hotspot.nodes.SerialArrayRangeWriteBarrier; import org.graalvm.compiler.hotspot.nodes.SerialWriteBarrier; -import org.graalvm.compiler.hotspot.nodes.type.NarrowOopStamp; +import org.graalvm.compiler.hotspot.nodes.VMErrorNode; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; @@ -78,17 +77,21 @@ import org.graalvm.compiler.nodes.memory.address.AddressNode; import org.graalvm.compiler.nodes.memory.address.AddressNode.Address; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.nodes.type.NarrowOopStamp; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.Log; import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; -import org.graalvm.compiler.replacements.nodes.DirectObjectStoreNode; import org.graalvm.compiler.replacements.nodes.DirectStoreNode; -import org.graalvm.compiler.word.Pointer; -import org.graalvm.compiler.word.Unsigned; import org.graalvm.compiler.word.Word; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.Pointer; +import org.graalvm.word.UnsignedWord; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.TargetDescription; @@ -96,41 +99,55 @@ import jdk.vm.ci.meta.JavaKind; public class WriteBarrierSnippets implements Snippets { - private static final SnippetCounter.Group countersWriteBarriers = SnippetCounters.getValue() ? new SnippetCounter.Group("WriteBarriers") : null; - private static final SnippetCounter serialWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialWriteBarrier", "Number of Serial Write Barriers"); - private static final SnippetCounter g1AttemptedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPreWriteBarrier", "Number of attempted G1 Pre Write Barriers"); - private static final SnippetCounter g1EffectivePreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectivePreWriteBarrier", "Number of effective G1 Pre Write Barriers"); - private static final SnippetCounter g1ExecutedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPreWriteBarrier", "Number of executed G1 Pre Write Barriers"); - private static final SnippetCounter g1AttemptedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPostWriteBarrier", "Number of attempted G1 Post Write Barriers"); - private static final SnippetCounter g1EffectiveAfterXORPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterXORPostWriteBarrier", - "Number of effective G1 Post Write Barriers (after passing the XOR test)"); - private static final SnippetCounter g1EffectiveAfterNullPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterNullPostWriteBarrier", - "Number of effective G1 Post Write Barriers (after passing the NULL test)"); - private static final SnippetCounter g1ExecutedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPostWriteBarrier", "Number of executed G1 Post Write Barriers"); + static class Counters { + Counters(SnippetCounter.Group.Factory factory) { + Group countersWriteBarriers = factory.createSnippetCounterGroup("WriteBarriers"); + serialWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "serialWriteBarrier", "Number of Serial Write Barriers"); + g1AttemptedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPreWriteBarrier", "Number of attempted G1 Pre Write Barriers"); + g1EffectivePreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectivePreWriteBarrier", "Number of effective G1 Pre Write Barriers"); + g1ExecutedPreWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPreWriteBarrier", "Number of executed G1 Pre Write Barriers"); + g1AttemptedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1AttemptedPostWriteBarrier", "Number of attempted G1 Post Write Barriers"); + g1EffectiveAfterXORPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterXORPostWriteBarrier", + "Number of effective G1 Post Write Barriers (after passing the XOR test)"); + g1EffectiveAfterNullPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1EffectiveAfterNullPostWriteBarrier", + "Number of effective G1 Post Write Barriers (after passing the NULL test)"); + g1ExecutedPostWriteBarrierCounter = new SnippetCounter(countersWriteBarriers, "g1ExecutedPostWriteBarrier", "Number of executed G1 Post Write Barriers"); + + } + + final SnippetCounter serialWriteBarrierCounter; + final SnippetCounter g1AttemptedPreWriteBarrierCounter; + final SnippetCounter g1EffectivePreWriteBarrierCounter; + final SnippetCounter g1ExecutedPreWriteBarrierCounter; + final SnippetCounter g1AttemptedPostWriteBarrierCounter; + final SnippetCounter g1EffectiveAfterXORPostWriteBarrierCounter; + final SnippetCounter g1EffectiveAfterNullPostWriteBarrierCounter; + final SnippetCounter g1ExecutedPostWriteBarrierCounter; + } public static final LocationIdentity GC_CARD_LOCATION = NamedLocationIdentity.mutable("GC-Card"); public static final LocationIdentity GC_LOG_LOCATION = NamedLocationIdentity.mutable("GC-Log"); public static final LocationIdentity GC_INDEX_LOCATION = NamedLocationIdentity.mutable("GC-Index"); - private static void serialWriteBarrier(Pointer ptr) { - serialWriteBarrierCounter.inc(); + private static void serialWriteBarrier(Pointer ptr, Counters counters) { + counters.serialWriteBarrierCounter.inc(); final long startAddress = GraalHotSpotVMConfigNode.cardTableAddress(); Word base = (Word) ptr.unsignedShiftRight(cardTableShift(INJECTED_VMCONFIG)); if (((int) startAddress) == startAddress && GraalHotSpotVMConfigNode.isCardTableAddressConstant()) { base.writeByte((int) startAddress, (byte) 0, GC_CARD_LOCATION); } else { - base.writeByte(Word.unsigned(startAddress), (byte) 0, GC_CARD_LOCATION); + base.writeByte(WordFactory.unsigned(startAddress), (byte) 0, GC_CARD_LOCATION); } } @Snippet - public static void serialImpreciseWriteBarrier(Object object) { - serialWriteBarrier(Word.objectToTrackedPointer(object)); + public static void serialImpreciseWriteBarrier(Object object, @ConstantParameter Counters counters) { + serialWriteBarrier(Word.objectToTrackedPointer(object), counters); } @Snippet - public static void serialPreciseWriteBarrier(Address address) { - serialWriteBarrier(Word.fromAddress(address)); + public static void serialPreciseWriteBarrier(Address address, @ConstantParameter Counters counters) { + serialWriteBarrier(Word.fromAddress(address), counters); } @Snippet @@ -154,26 +171,27 @@ public class WriteBarrierSnippets implements Snippets { @Snippet public static void g1PreWriteBarrier(Address address, Object object, Object expectedObject, @ConstantParameter boolean doLoad, @ConstantParameter boolean nullCheck, - @ConstantParameter Register threadRegister, @ConstantParameter boolean trace) { + @ConstantParameter Register threadRegister, @ConstantParameter boolean trace, @ConstantParameter Counters counters) { if (nullCheck) { NullCheckNode.nullCheck(address); } Word thread = registerAsWord(threadRegister); verifyOop(object); Object fixedExpectedObject = FixedValueAnchorNode.getObject(expectedObject); - Pointer field = Word.fromAddress(address); + Word field = Word.fromAddress(address); Pointer previousOop = Word.objectToTrackedPointer(fixedExpectedObject); byte markingValue = thread.readByte(g1SATBQueueMarkingOffset(INJECTED_VMCONFIG)); int gcCycle = 0; if (trace) { - gcCycle = (int) Word.unsigned(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG)).readLong(0); + Pointer gcTotalCollectionsAddress = WordFactory.pointer(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG)); + gcCycle = (int) gcTotalCollectionsAddress.readLong(0); log(trace, "[%d] G1-Pre Thread %p Object %p\n", gcCycle, thread.rawValue(), Word.objectToTrackedPointer(object).rawValue()); log(trace, "[%d] G1-Pre Thread %p Expected Object %p\n", gcCycle, thread.rawValue(), Word.objectToTrackedPointer(fixedExpectedObject).rawValue()); log(trace, "[%d] G1-Pre Thread %p Field %p\n", gcCycle, thread.rawValue(), field.rawValue()); log(trace, "[%d] G1-Pre Thread %p Marking %d\n", gcCycle, thread.rawValue(), markingValue); log(trace, "[%d] G1-Pre Thread %p DoLoad %d\n", gcCycle, thread.rawValue(), doLoad ? 1L : 0L); } - g1AttemptedPreWriteBarrierCounter.inc(); + counters.g1AttemptedPreWriteBarrierCounter.inc(); // If the concurrent marker is enabled, the barrier is issued. if (probability(NOT_FREQUENT_PROBABILITY, markingValue != (byte) 0)) { // If the previous value has to be loaded (before the write), the load is issued. @@ -185,10 +203,10 @@ public class WriteBarrierSnippets implements Snippets { verifyOop(previousOop.toObject()); } } - g1EffectivePreWriteBarrierCounter.inc(); + counters.g1EffectivePreWriteBarrierCounter.inc(); // If the previous value is null the barrier should not be issued. if (probability(FREQUENT_PROBABILITY, previousOop.notEqual(0))) { - g1ExecutedPreWriteBarrierCounter.inc(); + counters.g1ExecutedPreWriteBarrierCounter.inc(); // If the thread-local SATB buffer is full issue a native call which will // initialize a new one and add the entry. Word indexAddress = thread.add(g1SATBQueueIndexOffset(INJECTED_VMCONFIG)); @@ -209,7 +227,7 @@ public class WriteBarrierSnippets implements Snippets { @Snippet public static void g1PostWriteBarrier(Address address, Object object, Object value, @ConstantParameter boolean usePrecise, @ConstantParameter Register threadRegister, - @ConstantParameter boolean trace) { + @ConstantParameter boolean trace, @ConstantParameter Counters counters) { Word thread = registerAsWord(threadRegister); Object fixedValue = FixedValueAnchorNode.getObject(value); verifyOop(object); @@ -223,7 +241,8 @@ public class WriteBarrierSnippets implements Snippets { } int gcCycle = 0; if (trace) { - gcCycle = (int) Word.unsigned(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG)).readLong(0); + Pointer gcTotalCollectionsAddress = WordFactory.pointer(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG)); + gcCycle = (int) gcTotalCollectionsAddress.readLong(0); log(trace, "[%d] G1-Post Thread: %p Object: %p\n", gcCycle, thread.rawValue(), Word.objectToTrackedPointer(object).rawValue()); log(trace, "[%d] G1-Post Thread: %p Field: %p\n", gcCycle, thread.rawValue(), oop.rawValue()); } @@ -231,37 +250,37 @@ public class WriteBarrierSnippets implements Snippets { // The result of the xor reveals whether the installed pointer crosses heap regions. // In case it does the write barrier has to be issued. final int logOfHeapRegionGrainBytes = GraalHotSpotVMConfigNode.logOfHeapRegionGrainBytes(); - Unsigned xorResult = (oop.xor(writtenValue)).unsignedShiftRight(logOfHeapRegionGrainBytes); + UnsignedWord xorResult = (oop.xor(writtenValue)).unsignedShiftRight(logOfHeapRegionGrainBytes); // Calculate the address of the card to be enqueued to the // thread local card queue. - Unsigned cardBase = oop.unsignedShiftRight(cardTableShift(INJECTED_VMCONFIG)); + UnsignedWord cardBase = oop.unsignedShiftRight(cardTableShift(INJECTED_VMCONFIG)); final long startAddress = GraalHotSpotVMConfigNode.cardTableAddress(); int displacement = 0; if (((int) startAddress) == startAddress && GraalHotSpotVMConfigNode.isCardTableAddressConstant()) { displacement = (int) startAddress; } else { - cardBase = cardBase.add(Word.unsigned(startAddress)); + cardBase = cardBase.add(WordFactory.unsigned(startAddress)); } Word cardAddress = (Word) cardBase.add(displacement); - g1AttemptedPostWriteBarrierCounter.inc(); + counters.g1AttemptedPostWriteBarrierCounter.inc(); if (probability(FREQUENT_PROBABILITY, xorResult.notEqual(0))) { - g1EffectiveAfterXORPostWriteBarrierCounter.inc(); + counters.g1EffectiveAfterXORPostWriteBarrierCounter.inc(); // If the written value is not null continue with the barrier addition. if (probability(FREQUENT_PROBABILITY, writtenValue.notEqual(0))) { byte cardByte = cardAddress.readByte(0, GC_CARD_LOCATION); - g1EffectiveAfterNullPostWriteBarrierCounter.inc(); + counters.g1EffectiveAfterNullPostWriteBarrierCounter.inc(); // If the card is already dirty, (hence already enqueued) skip the insertion. if (probability(NOT_FREQUENT_PROBABILITY, cardByte != g1YoungCardValue(INJECTED_VMCONFIG))) { MembarNode.memoryBarrier(STORE_LOAD, GC_CARD_LOCATION); byte cardByteReload = cardAddress.readByte(0, GC_CARD_LOCATION); if (probability(NOT_FREQUENT_PROBABILITY, cardByteReload != dirtyCardValue(INJECTED_VMCONFIG))) { - log(trace, "[%d] G1-Post Thread: %p Card: %p \n", gcCycle, thread.rawValue(), Word.unsigned(cardByte).rawValue()); + log(trace, "[%d] G1-Post Thread: %p Card: %p \n", gcCycle, thread.rawValue(), WordFactory.unsigned((int) cardByte).rawValue()); cardAddress.writeByte(0, (byte) 0, GC_CARD_LOCATION); - g1ExecutedPostWriteBarrierCounter.inc(); + counters.g1ExecutedPostWriteBarrierCounter.inc(); // If the thread local card queue is full, issue a native call which will // initialize a new one and add the card entry. @@ -301,16 +320,16 @@ public class WriteBarrierSnippets implements Snippets { int header = arrayBaseOffset(JavaKind.Object); for (int i = startIndex; i < length; i++) { - long address = dstAddr + header + (i * scale); - Pointer oop = Word.objectToTrackedPointer(Word.unsigned(address).readObject(0, BarrierType.NONE)); + Word address = WordFactory.pointer(dstAddr + header + (i * scale)); + Pointer oop = Word.objectToTrackedPointer(address.readObject(0, BarrierType.NONE)); verifyOop(oop.toObject()); if (oop.notEqual(0)) { if (indexValue != 0) { indexValue = indexValue - wordSize(); - Word logAddress = bufferAddress.add(Word.unsigned(indexValue)); + Word logAddress = bufferAddress.add(WordFactory.unsigned(indexValue)); // Log the object to be marked as well as update the SATB's buffer next index. logAddress.writeWord(0, oop, GC_LOG_LOCATION); - indexAddress.writeWord(0, Word.unsigned(indexValue), GC_INDEX_LOCATION); + indexAddress.writeWord(0, WordFactory.unsigned(indexValue), GC_INDEX_LOCATION); } else { g1PreBarrierStub(G1WBPRECALL, oop.toObject()); } @@ -339,7 +358,7 @@ public class WriteBarrierSnippets implements Snippets { long count = end - start + 1; while (count-- > 0) { - Word cardAddress = Word.unsigned((start + cardStart) + count); + Word cardAddress = WordFactory.unsigned((start + cardStart) + count); byte cardByte = cardAddress.readByte(0, GC_CARD_LOCATION); // If the card is already dirty, (hence already enqueued) skip the insertion. if (probability(NOT_FREQUENT_PROBABILITY, cardByte != g1YoungCardValue(INJECTED_VMCONFIG))) { @@ -351,11 +370,11 @@ public class WriteBarrierSnippets implements Snippets { // initialize a new one and add the card entry. if (indexValue != 0) { indexValue = indexValue - wordSize(); - Word logAddress = bufferAddress.add(Word.unsigned(indexValue)); + Word logAddress = bufferAddress.add(WordFactory.unsigned(indexValue)); // Log the object to be scanned as well as update // the card queue's next index. logAddress.writeWord(0, cardAddress, GC_LOG_LOCATION); - indexAddress.writeWord(0, Word.unsigned(indexValue), GC_INDEX_LOCATION); + indexAddress.writeWord(0, WordFactory.unsigned(indexValue), GC_INDEX_LOCATION); } else { g1PostBarrierStub(G1WBPOSTCALL, cardAddress); } @@ -386,10 +405,13 @@ public class WriteBarrierSnippets implements Snippets { private final SnippetInfo g1ArrayRangePostWriteBarrier = snippet(WriteBarrierSnippets.class, "g1ArrayRangePostWriteBarrier", GC_CARD_LOCATION, GC_INDEX_LOCATION, GC_LOG_LOCATION); private final CompressEncoding oopEncoding; + private final Counters counters; - public Templates(HotSpotProviders providers, TargetDescription target, CompressEncoding oopEncoding) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target, + CompressEncoding oopEncoding) { + super(options, factories, providers, providers.getSnippetReflection(), target); this.oopEncoding = oopEncoding; + this.counters = new Counters(factory); } public void lower(SerialWriteBarrier writeBarrier, LoweringTool tool) { @@ -402,7 +424,8 @@ public class WriteBarrierSnippets implements Snippets { OffsetAddressNode address = (OffsetAddressNode) writeBarrier.getAddress(); args.add("object", address.getBase()); } - template(args).instantiate(providers.getMetaAccess(), writeBarrier, DEFAULT_REPLACER, args); + args.addConst("counters", counters); + template(writeBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), writeBarrier, DEFAULT_REPLACER, args); } public void lower(SerialArrayRangeWriteBarrier arrayRangeWriteBarrier, LoweringTool tool) { @@ -410,7 +433,7 @@ public class WriteBarrierSnippets implements Snippets { args.add("object", arrayRangeWriteBarrier.getObject()); args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); args.add("length", arrayRangeWriteBarrier.getLength()); - template(args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); + template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } public void lower(G1PreWriteBarrier writeBarrierPre, HotSpotRegistersProvider registers, LoweringTool tool) { @@ -426,15 +449,16 @@ public class WriteBarrierSnippets implements Snippets { ValueNode expected = writeBarrierPre.getExpectedObject(); if (expected != null && expected.stamp() instanceof NarrowOopStamp) { assert oopEncoding != null; - expected = CompressionNode.uncompress(expected, oopEncoding); + expected = HotSpotCompressionNode.uncompress(expected, oopEncoding); } args.add("expectedObject", expected); args.addConst("doLoad", writeBarrierPre.doLoad()); args.addConst("nullCheck", writeBarrierPre.getNullCheck()); args.addConst("threadRegister", registers.getThreadRegister()); - args.addConst("trace", traceBarrier()); - template(args).instantiate(providers.getMetaAccess(), writeBarrierPre, DEFAULT_REPLACER, args); + args.addConst("trace", traceBarrier(writeBarrierPre.graph())); + args.addConst("counters", counters); + template(writeBarrierPre.getDebug(), args).instantiate(providers.getMetaAccess(), writeBarrierPre, DEFAULT_REPLACER, args); } public void lower(G1ReferentFieldReadBarrier readBarrier, HotSpotRegistersProvider registers, LoweringTool tool) { @@ -450,15 +474,16 @@ public class WriteBarrierSnippets implements Snippets { ValueNode expected = readBarrier.getExpectedObject(); if (expected != null && expected.stamp() instanceof NarrowOopStamp) { assert oopEncoding != null; - expected = CompressionNode.uncompress(expected, oopEncoding); + expected = HotSpotCompressionNode.uncompress(expected, oopEncoding); } args.add("expectedObject", expected); args.addConst("doLoad", readBarrier.doLoad()); args.addConst("nullCheck", false); args.addConst("threadRegister", registers.getThreadRegister()); - args.addConst("trace", traceBarrier()); - template(args).instantiate(providers.getMetaAccess(), readBarrier, DEFAULT_REPLACER, args); + args.addConst("trace", traceBarrier(readBarrier.graph())); + args.addConst("counters", counters); + template(readBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), readBarrier, DEFAULT_REPLACER, args); } public void lower(G1PostWriteBarrier writeBarrierPost, HotSpotRegistersProvider registers, LoweringTool tool) { @@ -480,14 +505,15 @@ public class WriteBarrierSnippets implements Snippets { ValueNode value = writeBarrierPost.getValue(); if (value.stamp() instanceof NarrowOopStamp) { assert oopEncoding != null; - value = CompressionNode.uncompress(value, oopEncoding); + value = HotSpotCompressionNode.uncompress(value, oopEncoding); } args.add("value", value); args.addConst("usePrecise", writeBarrierPost.usePrecise()); args.addConst("threadRegister", registers.getThreadRegister()); - args.addConst("trace", traceBarrier()); - template(args).instantiate(providers.getMetaAccess(), writeBarrierPost, DEFAULT_REPLACER, args); + args.addConst("trace", traceBarrier(writeBarrierPost.graph())); + args.addConst("counters", counters); + template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), writeBarrierPost, DEFAULT_REPLACER, args); } public void lower(G1ArrayRangePreWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers, LoweringTool tool) { @@ -496,7 +522,7 @@ public class WriteBarrierSnippets implements Snippets { args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); args.add("length", arrayRangeWriteBarrier.getLength()); args.addConst("threadRegister", registers.getThreadRegister()); - template(args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); + template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } public void lower(G1ArrayRangePostWriteBarrier arrayRangeWriteBarrier, HotSpotRegistersProvider registers, LoweringTool tool) { @@ -505,7 +531,7 @@ public class WriteBarrierSnippets implements Snippets { args.add("startIndex", arrayRangeWriteBarrier.getStartIndex()); args.add("length", arrayRangeWriteBarrier.getLength()); args.addConst("threadRegister", registers.getThreadRegister()); - template(args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); + template(arrayRangeWriteBarrier.getDebug(), args).instantiate(providers.getMetaAccess(), arrayRangeWriteBarrier, DEFAULT_REPLACER, args); } } @@ -530,9 +556,10 @@ public class WriteBarrierSnippets implements Snippets { } } - public static boolean traceBarrier() { - return GraalOptions.GCDebugStartCycle.getValue() > 0 && - ((int) Word.unsigned(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG)).readLong(0) > GraalOptions.GCDebugStartCycle.getValue()); + public static boolean traceBarrier(StructuredGraph graph) { + return GraalOptions.GCDebugStartCycle.getValue(graph.getOptions()) > 0 && + ((int) ((Pointer) WordFactory.pointer(HotSpotReplacementsUtil.gcTotalCollectionsAddress(INJECTED_VMCONFIG))).readLong(0) > GraalOptions.GCDebugStartCycle.getValue( + graph.getOptions())); } /** @@ -544,7 +571,7 @@ public class WriteBarrierSnippets implements Snippets { public static void validateObject(Object parent, Object child) { if (verifyOops(INJECTED_VMCONFIG) && child != null && !validateOop(VALIDATE_OBJECT, parent, child)) { log(true, "Verification ERROR, Parent: %p Child: %p\n", Word.objectToTrackedPointer(parent).rawValue(), Word.objectToTrackedPointer(child).rawValue()); - DirectObjectStoreNode.storeObject(null, 0, 0, null, LocationIdentity.any(), JavaKind.Object); + VMErrorNode.vmError("Verification ERROR, Parent: %p\n", Word.objectToTrackedPointer(parent).rawValue()); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java index 7b0f000f6ed..7cc363e8e41 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java @@ -27,6 +27,7 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probabil import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; import org.graalvm.compiler.api.replacements.Snippet; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -48,6 +49,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -113,8 +115,8 @@ public class ResolveConstantSnippets implements Snippets { private final SnippetInfo initializeKlass = snippet(ResolveConstantSnippets.class, "initializeKlass"); private final SnippetInfo pureInitializeKlass = snippet(ResolveConstantSnippets.class, "pureInitializeKlass"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); } public void lower(ResolveConstantNode resolveConstantNode, LoweringTool tool) { @@ -147,8 +149,8 @@ public class ResolveConstantSnippets implements Snippets { Arguments args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage()); args.add("constant", value); - SnippetTemplate template = template(args); - template.instantiate(providers.getMetaAccess(), resolveConstantNode, DEFAULT_REPLACER, tool, args); + SnippetTemplate template = template(graph.getDebug(), args); + template.instantiate(providers.getMetaAccess(), resolveConstantNode, DEFAULT_REPLACER, args); assert resolveConstantNode.hasNoUsages(); if (!resolveConstantNode.isDeleted()) { @@ -167,7 +169,7 @@ public class ResolveConstantSnippets implements Snippets { Arguments args = new Arguments(initializeKlass, graph.getGuardsStage(), tool.getLoweringStage()); args.add("constant", value); - SnippetTemplate template = template(args); + SnippetTemplate template = template(graph.getDebug(), args); template.instantiate(providers.getMetaAccess(), initializeKlassNode, DEFAULT_REPLACER, args); assert initializeKlassNode.hasNoUsages(); if (!initializeKlassNode.isDeleted()) { @@ -185,8 +187,8 @@ public class ResolveConstantSnippets implements Snippets { Arguments args = new Arguments(resolveMethodAndLoadCounters, graph.getGuardsStage(), tool.getLoweringStage()); args.add("method", method); args.add("klassHint", resolveMethodAndLoadCountersNode.getHub()); - SnippetTemplate template = template(args); - template.instantiate(providers.getMetaAccess(), resolveMethodAndLoadCountersNode, DEFAULT_REPLACER, tool, args); + SnippetTemplate template = template(graph.getDebug(), args); + template.instantiate(providers.getMetaAccess(), resolveMethodAndLoadCountersNode, DEFAULT_REPLACER, args); assert resolveMethodAndLoadCountersNode.hasNoUsages(); if (!resolveMethodAndLoadCountersNode.isDeleted()) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java index 50618b2e513..8f4e370020f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java @@ -29,7 +29,6 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; @@ -58,6 +57,7 @@ import org.graalvm.compiler.nodes.memory.MemoryNode; import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.meta.JavaConstant; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java index 803ee73d6e5..61170a8427c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java @@ -22,22 +22,21 @@ */ package org.graalvm.compiler.hotspot.replacements.arraycopy; -import jdk.vm.ci.meta.JavaKind; +import static org.graalvm.word.LocationIdentity.any; -import static org.graalvm.compiler.core.common.LocationIdentity.any; - -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; -import org.graalvm.compiler.nodes.spi.Virtualizable; import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; +import org.graalvm.word.LocationIdentity; + +import jdk.vm.ci.meta.JavaKind; @NodeInfo -public final class ArrayCopyNode extends BasicArrayCopyNode implements Virtualizable, Lowerable { +public final class ArrayCopyNode extends BasicArrayCopyNode implements Lowerable { public static final NodeClass TYPE = NodeClass.create(ArrayCopyNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySlowPathNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySlowPathNode.java index 4111f702394..99591564e3d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySlowPathNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySlowPathNode.java @@ -25,9 +25,8 @@ package org.graalvm.compiler.hotspot.replacements.arraycopy; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.meta.JavaKind; -import static org.graalvm.compiler.core.common.LocationIdentity.any; +import static org.graalvm.word.LocationIdentity.any; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodeinfo.InputType; @@ -37,6 +36,7 @@ import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; +import org.graalvm.word.LocationIdentity; @NodeInfo(allowedUsageTypes = InputType.Memory) public final class ArrayCopySlowPathNode extends BasicArrayCopyNode { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java index 08eab361382..bf68c43c48f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java @@ -22,7 +22,6 @@ */ package org.graalvm.compiler.hotspot.replacements.arraycopy; -import static org.graalvm.compiler.core.common.GraalOptions.SnippetCounters; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.KLASS_SUPER_CHECK_OFFSET_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION; @@ -39,13 +38,12 @@ import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probabil import java.lang.reflect.Method; import java.util.EnumMap; -import java.util.Map; import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.LocationIdentity; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -60,19 +58,25 @@ import org.graalvm.compiler.nodes.NamedLocationIdentity; import org.graalvm.compiler.nodes.PiNode; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; +import org.graalvm.compiler.nodes.extended.RawLoadNode; +import org.graalvm.compiler.nodes.extended.RawStoreNode; import org.graalvm.compiler.nodes.java.ArrayLengthNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.type.StampTool; +import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetCounter; +import org.graalvm.compiler.replacements.SnippetCounter.Group; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode; -import org.graalvm.compiler.replacements.nodes.DirectObjectStoreNode; import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode; import org.graalvm.compiler.word.Word; +import org.graalvm.util.UnmodifiableEconomicMap; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; @@ -85,64 +89,64 @@ import jdk.vm.ci.meta.ResolvedJavaType; public class ArrayCopySnippets implements Snippets { - private static int checkArrayType(KlassPointer hub) { - int layoutHelper = readLayoutHelper(hub); + private static int checkArrayType(KlassPointer nonNullHub) { + int layoutHelper = readLayoutHelper(nonNullHub); if (probability(SLOW_PATH_PROBABILITY, layoutHelper >= 0)) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } return layoutHelper; } - private static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length) { + private static void checkLimits(Object src, int srcPos, Object dest, int destPos, int length, Counters counters) { if (probability(SLOW_PATH_PROBABILITY, srcPos < 0)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (probability(SLOW_PATH_PROBABILITY, destPos < 0)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (probability(SLOW_PATH_PROBABILITY, length < 0)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (probability(SLOW_PATH_PROBABILITY, srcPos > ArrayLengthNode.arrayLength(src) - length)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } if (probability(SLOW_PATH_PROBABILITY, destPos > ArrayLengthNode.arrayLength(dest) - length)) { - checkAIOOBECounter.inc(); + counters.checkAIOOBECounter.inc(); DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - checkSuccessCounter.inc(); + counters.checkSuccessCounter.inc(); } @Snippet - public static void arraycopyZeroLengthIntrinsic(Object src, int srcPos, Object dest, int destPos, int length) { + public static void arraycopyZeroLengthIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); KlassPointer srcHub = loadHub(nonNullSrc); KlassPointer destHub = loadHub(nonNullDest); checkArrayType(srcHub); checkArrayType(destHub); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); - zeroLengthStaticCounter.inc(); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); + counters.zeroLengthStaticCounter.inc(); } @Snippet public static void arraycopyExactIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, @ConstantParameter SnippetCounter counter, - @ConstantParameter SnippetCounter copiedCounter) { + @ConstantParameter SnippetCounter copiedCounter, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); counter.inc(); copiedCounter.add(length); ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind); if (length == 0) { - zeroLengthDynamicCounter.inc(); + counters.zeroLengthDynamicCounter.inc(); } else { - nonZeroLengthDynamicCounter.inc(); - nonZeroLengthDynamicCopiedCounter.add(length); + counters.nonZeroLengthDynamicCounter.inc(); + counters.nonZeroLengthDynamicCopiedCounter.add(length); } } @@ -152,7 +156,7 @@ public class ArrayCopySnippets implements Snippets { */ @Snippet public static void arraycopyPredictedExactIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter JavaKind elementKind, - @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter) { + @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); KlassPointer srcHub = loadHub(nonNullSrc); @@ -160,33 +164,33 @@ public class ArrayCopySnippets implements Snippets { if (probability(SLOW_PATH_PROBABILITY, srcHub != destHub)) { DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint); } - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); counter.inc(); copiedCounter.add(length); ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, elementKind); if (length == 0) { - zeroLengthDynamicCounter.inc(); + counters.zeroLengthDynamicCounter.inc(); } else { - nonZeroLengthDynamicCounter.inc(); - nonZeroLengthDynamicCopiedCounter.add(length); + counters.nonZeroLengthDynamicCounter.inc(); + counters.nonZeroLengthDynamicCopiedCounter.add(length); } } @Snippet public static void arraycopyPredictedObjectWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, KlassPointer objectArrayKlass, - @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter) { + @ConstantParameter SnippetCounter counter, @ConstantParameter SnippetCounter copiedCounter, @ConstantParameter Counters counters) { if (length > 0) { KlassPointer srcHub = loadHub(PiNode.asNonNullObject(nonNullSrc)); KlassPointer destHub = loadHub(PiNode.asNonNullObject(nonNullDest)); if (probability(FAST_PATH_PROBABILITY, srcHub == destHub || destHub == objectArrayKlass)) { counter.inc(); copiedCounter.add(length); - predictedObjectArrayCopyFastPathCounter.inc(); - predictedObjectArrayCopyFastPathCopiedCounter.add(length); + counters.predictedObjectArrayCopyFastPathCounter.inc(); + counters.predictedObjectArrayCopyFastPathCopiedCounter.add(length); ArrayCopyCallNode.arraycopyObjectKillsAny(nonNullSrc, srcPos, nonNullDest, destPos, length); } else { - predictedObjectArrayCopySlowPathCounter.inc(); - predictedObjectArrayCopySlowPathCopiedCounter.add(length); + counters.predictedObjectArrayCopySlowPathCounter.inc(); + counters.predictedObjectArrayCopySlowPathCopiedCounter.add(length); System.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length); } } @@ -198,19 +202,19 @@ public class ArrayCopySnippets implements Snippets { */ @Snippet public static void arraycopySlowPathIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, KlassPointer predictedKlass, @ConstantParameter JavaKind elementKind, - @ConstantParameter SnippetInfo slowPath, @ConstantParameter Object slowPathArgument) { + @ConstantParameter SnippetInfo slowPath, @ConstantParameter Object slowPathArgument, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); KlassPointer srcHub = loadHub(nonNullSrc); KlassPointer destHub = loadHub(nonNullDest); checkArrayType(srcHub); checkArrayType(destHub); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); if (length == 0) { - zeroLengthDynamicCounter.inc(); + counters.zeroLengthDynamicCounter.inc(); } else { - nonZeroLengthDynamicCounter.inc(); - nonZeroLengthDynamicCopiedCounter.add(length); + counters.nonZeroLengthDynamicCounter.inc(); + counters.nonZeroLengthDynamicCopiedCounter.add(length); } ArrayCopySlowPathNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, predictedKlass, elementKind, slowPath, slowPathArgument); } @@ -219,34 +223,35 @@ public class ArrayCopySnippets implements Snippets { * Snippet for unrolled arraycopy. */ @Snippet - public static void arraycopyUnrolledIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter int unrolledLength, @ConstantParameter JavaKind elementKind) { + public static void arraycopyUnrolledIntrinsic(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter int unrolledLength, @ConstantParameter JavaKind elementKind, + @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); if (length == 0) { - zeroLengthDynamicCounter.inc(); + counters.zeroLengthDynamicCounter.inc(); } else { - nonZeroLengthDynamicCounter.inc(); - nonZeroLengthDynamicCopiedCounter.add(length); + counters.nonZeroLengthDynamicCounter.inc(); + counters.nonZeroLengthDynamicCopiedCounter.add(length); } ArrayCopyUnrollNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, unrolledLength, elementKind); } @Snippet - public static void checkcastArraycopyWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length) { + public static void checkcastArraycopyWork(Object nonNullSrc, int srcPos, Object nonNullDest, int destPos, int length, @ConstantParameter Counters counters) { if (length > 0) { KlassPointer destKlass = loadHub(nonNullDest); KlassPointer srcKlass = loadHub(nonNullSrc); if (probability(SLOW_PATH_PROBABILITY, srcKlass == destKlass)) { // no storecheck required. - objectCheckcastSameTypeCounter.inc(); - objectCheckcastSameTypeCopiedCounter.add(length); + counters.objectCheckcastSameTypeCounter.inc(); + counters.objectCheckcastSameTypeCopiedCounter.add(length); ArrayCopyCallNode.arraycopyObjectKillsAny(nonNullSrc, srcPos, nonNullDest, destPos, length); } else { KlassPointer destElemKlass = destKlass.readKlassPointer(arrayClassElementOffset(INJECTED_VMCONFIG), OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION); - Word superCheckOffset = Word.signed(destElemKlass.readInt(superCheckOffsetOffset(INJECTED_VMCONFIG), KLASS_SUPER_CHECK_OFFSET_LOCATION)); - objectCheckcastCounter.inc(); - objectCheckcastCopiedCounter.add(length); + Word superCheckOffset = WordFactory.signed(destElemKlass.readInt(superCheckOffsetOffset(INJECTED_VMCONFIG), KLASS_SUPER_CHECK_OFFSET_LOCATION)); + counters.objectCheckcastCounter.inc(); + counters.objectCheckcastCopiedCounter.add(length); int copiedElements = CheckcastArrayCopyCallNode.checkcastArraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, superCheckOffset, destElemKlass, false); if (copiedElements != 0) { /* @@ -261,7 +266,7 @@ public class ArrayCopySnippets implements Snippets { } @Snippet - public static void arraycopyGeneric(Object src, int srcPos, Object dest, int destPos, int length) { + public static void arraycopyGeneric(Object src, int srcPos, Object dest, int destPos, int length, @ConstantParameter Counters counters) { Object nonNullSrc = GraalDirectives.guardingNonNull(src); Object nonNullDest = GraalDirectives.guardingNonNull(dest); KlassPointer srcHub = loadHub(nonNullSrc); @@ -269,19 +274,19 @@ public class ArrayCopySnippets implements Snippets { if (probability(FAST_PATH_PROBABILITY, srcHub.equal(destHub)) && probability(FAST_PATH_PROBABILITY, nonNullSrc != nonNullDest)) { int layoutHelper = checkArrayType(srcHub); final boolean isObjectArray = ((layoutHelper & layoutHelperElementTypePrimitiveInPlace(INJECTED_VMCONFIG)) == 0); - checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); + checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length, counters); if (probability(FAST_PATH_PROBABILITY, isObjectArray)) { - genericObjectExactCallCounter.inc(); - genericObjectExactCallCopiedCounter.add(length); + counters.genericObjectExactCallCounter.inc(); + counters.genericObjectExactCallCopiedCounter.add(length); ArrayCopyCallNode.disjointArraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, JavaKind.Object); } else { - genericPrimitiveCallCounter.inc(); - genericPrimitiveCallCopiedCounter.add(length); + counters.genericPrimitiveCallCounter.inc(); + counters.genericPrimitiveCallCopiedCounter.add(length); UnsafeArrayCopyNode.arraycopyPrimitive(nonNullSrc, srcPos, nonNullDest, destPos, length, layoutHelper); } } else { - SystemArraycopyCounter.inc(); - SystemArraycopyCopiedCounter.add(length); + counters.systemArraycopyCounter.inc(); + counters.systemArraycopyCopiedCounter.add(length); System.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length); } } @@ -302,8 +307,8 @@ public class ArrayCopySnippets implements Snippets { ExplodeLoopNode.explodeLoop(); for (int iteration = 0; iteration < length; iteration++) { if (i >= 0) { - Object a = UnsafeLoadNode.load(nonNullSrc, arrayBaseOffset + i + (long) srcPos * scale, elementKind, arrayLocation); - DirectObjectStoreNode.storeObject(nonNullDest, arrayBaseOffset, i + (long) destPos * scale, a, arrayLocation, elementKind); + Object a = RawLoadNode.load(nonNullSrc, arrayBaseOffset + i + (long) srcPos * scale, elementKind, arrayLocation); + RawStoreNode.storeObject(nonNullDest, arrayBaseOffset + i + (long) destPos * scale, a, elementKind, arrayLocation, false); i -= scale; } } @@ -313,78 +318,103 @@ public class ArrayCopySnippets implements Snippets { ExplodeLoopNode.explodeLoop(); for (int iteration = 0; iteration < length; iteration++) { if (i < end) { - Object a = UnsafeLoadNode.load(nonNullSrc, arrayBaseOffset + i + (long) srcPos * scale, elementKind, arrayLocation); - DirectObjectStoreNode.storeObject(nonNullDest, arrayBaseOffset, i + (long) destPos * scale, a, arrayLocation, elementKind); + Object a = RawLoadNode.load(nonNullSrc, arrayBaseOffset + i + (long) srcPos * scale, elementKind, arrayLocation); + RawStoreNode.storeObject(nonNullDest, arrayBaseOffset + i + (long) destPos * scale, a, elementKind, arrayLocation, false); i += scale; } } } } - private static final SnippetCounter.Group checkCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy checkInputs") : null; - private static final SnippetCounter checkSuccessCounter = new SnippetCounter(checkCounters, "checkSuccess", "checkSuccess"); - private static final SnippetCounter checkAIOOBECounter = new SnippetCounter(checkCounters, "checkAIOOBE", "checkAIOOBE"); + static class Counters { + final SnippetCounter checkSuccessCounter; + final SnippetCounter checkAIOOBECounter; - private static final SnippetCounter.Group counters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy") : null; + final SnippetCounter objectCheckcastCounter; + final SnippetCounter objectCheckcastSameTypeCounter; + final SnippetCounter predictedObjectArrayCopySlowPathCounter; + final SnippetCounter predictedObjectArrayCopyFastPathCounter; - private static final SnippetCounter objectCheckcastCounter = new SnippetCounter(counters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays"); - private static final SnippetCounter objectCheckcastSameTypeCounter = new SnippetCounter(counters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays"); - private static final SnippetCounter predictedObjectArrayCopySlowPathCounter = new SnippetCounter(counters, "Object[]{slow-path}", "used System.arraycopy slow path for predicted Object[] arrays"); - private static final SnippetCounter predictedObjectArrayCopyFastPathCounter = new SnippetCounter(counters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays"); + final SnippetCounter genericPrimitiveCallCounter; + final SnippetCounter genericObjectExactCallCounter; + final SnippetCounter systemArraycopyCounter; - private static final EnumMap arraycopyCallCounters = new EnumMap<>(JavaKind.class); - private static final EnumMap arraycopyCounters = new EnumMap<>(JavaKind.class); + final SnippetCounter zeroLengthStaticCounter; + final SnippetCounter zeroLengthDynamicCounter; + final SnippetCounter nonZeroLengthDynamicCounter; - private static final EnumMap arraycopyCallCopiedCounters = new EnumMap<>(JavaKind.class); - private static final EnumMap arraycopyCopiedCounters = new EnumMap<>(JavaKind.class); + final SnippetCounter nonZeroLengthDynamicCopiedCounter; + final SnippetCounter genericPrimitiveCallCopiedCounter; + final SnippetCounter genericObjectExactCallCopiedCounter; + final SnippetCounter systemArraycopyCopiedCounter; - static void createArraycopyCounter(JavaKind kind) { - arraycopyCallCounters.put(kind, new SnippetCounter(counters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays")); - arraycopyCounters.put(kind, new SnippetCounter(counters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays")); + final SnippetCounter objectCheckcastCopiedCounter; + final SnippetCounter objectCheckcastSameTypeCopiedCounter; + final SnippetCounter predictedObjectArrayCopySlowPathCopiedCounter; + final SnippetCounter predictedObjectArrayCopyFastPathCopiedCounter; - arraycopyCallCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays")); - arraycopyCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays")); + final EnumMap arraycopyCallCounters = new EnumMap<>(JavaKind.class); + final EnumMap arraycopyCounters = new EnumMap<>(JavaKind.class); + + final EnumMap arraycopyCallCopiedCounters = new EnumMap<>(JavaKind.class); + final EnumMap arraycopyCopiedCounters = new EnumMap<>(JavaKind.class); + + Counters(SnippetCounter.Group.Factory factory) { + final Group checkCounters = factory.createSnippetCounterGroup("System.arraycopy checkInputs"); + final Group counters = factory.createSnippetCounterGroup("System.arraycopy"); + final Group copiedCounters = factory.createSnippetCounterGroup("System.arraycopy copied elements"); + final Group lengthCounters = factory.createSnippetCounterGroup("System.arraycopy 0-length checks"); + + checkSuccessCounter = new SnippetCounter(checkCounters, "checkSuccess", "checkSuccess"); + checkAIOOBECounter = new SnippetCounter(checkCounters, "checkAIOOBE", "checkAIOOBE"); + + objectCheckcastCounter = new SnippetCounter(counters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays"); + objectCheckcastSameTypeCounter = new SnippetCounter(counters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays"); + predictedObjectArrayCopySlowPathCounter = new SnippetCounter(counters, "Object[]{slow-path}", "used System.arraycopy slow path for predicted Object[] arrays"); + predictedObjectArrayCopyFastPathCounter = new SnippetCounter(counters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays"); + genericPrimitiveCallCounter = new SnippetCounter(counters, "genericPrimitive", "generic arraycopy snippet for primitive arrays"); + genericObjectExactCallCounter = new SnippetCounter(counters, "genericObjectExact", "generic arraycopy snippet for special object arrays"); + systemArraycopyCounter = new SnippetCounter(counters, "genericObject", "call to System.arraycopy"); + + zeroLengthStaticCounter = new SnippetCounter(lengthCounters, "0-lengthcopy static", "arraycopy where the length is statically 0"); + zeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "0-lengthcopy dynamically", "arraycopy where the length is dynamically 0"); + nonZeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero"); + + nonZeroLengthDynamicCopiedCounter = new SnippetCounter(copiedCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero"); + genericPrimitiveCallCopiedCounter = new SnippetCounter(copiedCounters, "genericPrimitive", "generic arraycopy snippet for primitive arrays"); + genericObjectExactCallCopiedCounter = new SnippetCounter(copiedCounters, "genericObjectExact", "generic arraycopy snippet for special object arrays"); + systemArraycopyCopiedCounter = new SnippetCounter(copiedCounters, "genericObject", "call to System.arraycopy"); + + objectCheckcastCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays"); + objectCheckcastSameTypeCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays"); + predictedObjectArrayCopySlowPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{slow-path}", + "used System.arraycopy slow path for predicted Object[] arrays"); + predictedObjectArrayCopyFastPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays"); + createArraycopyCounter(JavaKind.Byte, counters, copiedCounters); + createArraycopyCounter(JavaKind.Boolean, counters, copiedCounters); + createArraycopyCounter(JavaKind.Char, counters, copiedCounters); + createArraycopyCounter(JavaKind.Short, counters, copiedCounters); + createArraycopyCounter(JavaKind.Int, counters, copiedCounters); + createArraycopyCounter(JavaKind.Long, counters, copiedCounters); + createArraycopyCounter(JavaKind.Float, counters, copiedCounters); + createArraycopyCounter(JavaKind.Double, counters, copiedCounters); + createArraycopyCounter(JavaKind.Object, counters, copiedCounters); + } + + void createArraycopyCounter(JavaKind kind, Group counters, Group copiedCounters) { + arraycopyCallCounters.put(kind, new SnippetCounter(counters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays")); + arraycopyCounters.put(kind, new SnippetCounter(counters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays")); + + arraycopyCallCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{stub}", "arraycopy call for " + kind + "[] arrays")); + arraycopyCopiedCounters.put(kind, new SnippetCounter(copiedCounters, kind + "[]{inline}", "inline arraycopy for " + kind + "[] arrays")); + } } - static { - createArraycopyCounter(JavaKind.Byte); - createArraycopyCounter(JavaKind.Boolean); - createArraycopyCounter(JavaKind.Char); - createArraycopyCounter(JavaKind.Short); - createArraycopyCounter(JavaKind.Int); - createArraycopyCounter(JavaKind.Long); - createArraycopyCounter(JavaKind.Float); - createArraycopyCounter(JavaKind.Double); - createArraycopyCounter(JavaKind.Object); - } - - private static final SnippetCounter genericPrimitiveCallCounter = new SnippetCounter(counters, "genericPrimitive", "generic arraycopy snippet for primitive arrays"); - private static final SnippetCounter genericObjectExactCallCounter = new SnippetCounter(counters, "genericObjectExact", "generic arraycopy snippet for special object arrays"); - private static final SnippetCounter SystemArraycopyCounter = new SnippetCounter(counters, "genericObject", "call to System.arraycopy"); - - private static final SnippetCounter.Group lengthCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy 0-length checks") : null; - - private static final SnippetCounter zeroLengthStaticCounter = new SnippetCounter(lengthCounters, "0-lengthcopy static", "arraycopy where the length is statically 0"); - private static final SnippetCounter zeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "0-lengthcopy dynamically", "arraycopy where the length is dynamically 0"); - private static final SnippetCounter nonZeroLengthDynamicCounter = new SnippetCounter(lengthCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero"); - - private static final SnippetCounter.Group copiedCounters = SnippetCounters.getValue() ? new SnippetCounter.Group("System.arraycopy copied elements") : null; - - private static final SnippetCounter nonZeroLengthDynamicCopiedCounter = new SnippetCounter(copiedCounters, "non-0-lengthcopy dynamically", "arraycopy where the length is dynamically not zero"); - private static final SnippetCounter genericPrimitiveCallCopiedCounter = new SnippetCounter(copiedCounters, "genericPrimitive", "generic arraycopy snippet for primitive arrays"); - private static final SnippetCounter genericObjectExactCallCopiedCounter = new SnippetCounter(copiedCounters, "genericObjectExact", "generic arraycopy snippet for special object arrays"); - private static final SnippetCounter SystemArraycopyCopiedCounter = new SnippetCounter(copiedCounters, "genericObject", "call to System.arraycopy"); - - private static final SnippetCounter objectCheckcastCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{non-exact}", "arraycopy for non-exact Object[] arrays"); - private static final SnippetCounter objectCheckcastSameTypeCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{same-type}", "arraycopy call for src.klass == dest.klass Object[] arrays"); - private static final SnippetCounter predictedObjectArrayCopySlowPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{slow-path}", - "used System.arraycopy slow path for predicted Object[] arrays"); - private static final SnippetCounter predictedObjectArrayCopyFastPathCopiedCounter = new SnippetCounter(copiedCounters, "Object[]{fast-path}", "used oop_arraycopy for predicted Object[] arrays"); - public static class Templates extends SnippetTemplate.AbstractTemplates { - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, SnippetCounter.Group.Factory factory, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); + this.counters = new Counters(factory); } private ResolvedJavaMethod originalArraycopy() throws GraalError { @@ -414,6 +444,8 @@ public class ArrayCopySnippets implements Snippets { private final SnippetInfo arraycopyUnrolledWorkSnippet = snippet("arraycopyUnrolledWork"); + private final Counters counters; + protected SnippetInfo snippet(String methodName) { SnippetInfo info = snippet(ArrayCopySnippets.class, methodName, LocationIdentity.any()); info.setOriginalMethod(originalArraycopy()); @@ -538,9 +570,10 @@ public class ArrayCopySnippets implements Snippets { } else if (snippetInfo == arraycopyExactIntrinsicSnippet || snippetInfo == arraycopyPredictedExactIntrinsicSnippet) { assert componentKind != null; args.addConst("elementKind", componentKind); - args.addConst("counter", arraycopyCallCounters.get(componentKind)); - args.addConst("copiedCounter", arraycopyCallCopiedCounters.get(componentKind)); + args.addConst("counter", counters.arraycopyCallCounters.get(componentKind)); + args.addConst("copiedCounter", counters.arraycopyCallCopiedCounters.get(componentKind)); } + args.addConst("counters", counters); instantiate(args, arraycopy); } @@ -564,8 +597,9 @@ public class ArrayCopySnippets implements Snippets { } if (snippetInfo == arraycopyPredictedObjectWorkSnippet) { args.add("objectArrayKlass", arraycopy.getPredictedKlass()); - args.addConst("counter", arraycopyCallCounters.get(JavaKind.Object)); - args.addConst("copiedCounter", arraycopyCallCopiedCounters.get(JavaKind.Object)); + args.addConst("counter", counters.arraycopyCallCounters.get(JavaKind.Object)); + args.addConst("copiedCounter", counters.arraycopyCallCopiedCounters.get(JavaKind.Object)); + args.addConst("counters", counters); } instantiate(args, arraycopy); } @@ -584,7 +618,7 @@ public class ArrayCopySnippets implements Snippets { args.add("destPos", arraycopy.getDestinationPosition()); args.addConst("length", arraycopy.getUnrollLength()); args.addConst("elementKind", arraycopy.getElementKind()); - template(args).instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args); + template(graph.getDebug(), args).instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args); } /** @@ -596,9 +630,9 @@ public class ArrayCopySnippets implements Snippets { */ private void instantiate(Arguments args, BasicArrayCopyNode arraycopy) { StructuredGraph graph = arraycopy.graph(); - SnippetTemplate template = template(args); - Map replacements = template.instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args); - for (Node originalNode : replacements.keySet()) { + SnippetTemplate template = template(graph.getDebug(), args); + UnmodifiableEconomicMap replacements = template.instantiate(providers.getMetaAccess(), arraycopy, SnippetTemplate.DEFAULT_REPLACER, args, false); + for (Node originalNode : replacements.getKeys()) { if (originalNode instanceof Invoke) { Invoke invoke = (Invoke) replacements.get(originalNode); assert invoke.asNode().graph() == graph; @@ -612,17 +646,18 @@ public class ArrayCopySnippets implements Snippets { if (arraycopy.stateDuring() != null) { newInvoke.setStateDuring(arraycopy.stateDuring()); } else { - assert arraycopy.stateAfter() != null; + assert arraycopy.stateAfter() != null : arraycopy; newInvoke.setStateAfter(arraycopy.stateAfter()); } graph.replaceFixedWithFixed((InvokeNode) invoke.asNode(), newInvoke); } else if (originalNode instanceof ArrayCopySlowPathNode) { ArrayCopySlowPathNode slowPath = (ArrayCopySlowPathNode) replacements.get(originalNode); - assert arraycopy.stateAfter() != null; - slowPath.setStateAfter(arraycopy.stateAfter()); + assert arraycopy.stateAfter() != null : arraycopy; + assert slowPath.stateAfter() == arraycopy.stateAfter(); slowPath.setBci(arraycopy.getBci()); } } + GraphUtil.killCFG(arraycopy); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyUnrollNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyUnrollNode.java index f0729b4e8e8..7bd998024d3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyUnrollNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyUnrollNode.java @@ -24,9 +24,8 @@ package org.graalvm.compiler.hotspot.replacements.arraycopy; import jdk.vm.ci.meta.JavaKind; -import static org.graalvm.compiler.core.common.LocationIdentity.any; +import static org.graalvm.word.LocationIdentity.any; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.InputType; @@ -39,6 +38,7 @@ import org.graalvm.compiler.nodes.memory.MemoryCheckpoint; import org.graalvm.compiler.nodes.memory.MemoryNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.word.LocationIdentity; @NodeInfo(allowedUsageTypes = InputType.Memory) public class ArrayCopyUnrollNode extends ArrayRangeWriteNode implements MemoryCheckpoint.Single, Lowerable, MemoryAccess { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java index 4f98f071012..8853e1a3b66 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java @@ -28,7 +28,6 @@ import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_UNKNOWN; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; @@ -51,6 +50,7 @@ import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.word.Word; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.meta.JavaKind; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopyNode.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopyNode.java index d904f2ae6d1..83c7c4f9f10 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopyNode.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopyNode.java @@ -22,11 +22,10 @@ */ package org.graalvm.compiler.hotspot.replacements.arraycopy; -import static org.graalvm.compiler.core.common.LocationIdentity.any; -import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_200; -import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_200; +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_256; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64; +import static org.graalvm.word.LocationIdentity.any; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.nodeinfo.InputType; @@ -40,10 +39,11 @@ import org.graalvm.compiler.nodes.memory.MemoryNode; import org.graalvm.compiler.nodes.spi.Lowerable; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.meta.JavaKind; -@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_200, size = SIZE_200) +@NodeInfo(allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_256, size = SIZE_64) public final class UnsafeArrayCopyNode extends ArrayRangeWriteNode implements Lowerable, MemoryCheckpoint.Single, MemoryAccess { public static final NodeClass TYPE = NodeClass.create(UnsafeArrayCopyNode.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java index 69cb5730036..71d63706deb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.hotspot.replacements.arraycopy; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayBaseOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayIndexScale; @@ -31,31 +32,32 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeShift; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.runtime; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; -import static org.graalvm.compiler.nodes.NamedLocationIdentity.any; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.probability; import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; +import static org.graalvm.word.LocationIdentity.any; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.api.replacements.Snippet; -import org.graalvm.compiler.asm.NumUtil; -import org.graalvm.compiler.core.common.LocationIdentity; +import org.graalvm.compiler.core.common.NumUtil; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.phases.WriteBarrierAdditionPhase; import org.graalvm.compiler.nodes.NamedLocationIdentity; +import org.graalvm.compiler.nodes.extended.RawLoadNode; +import org.graalvm.compiler.nodes.extended.RawStoreNode; import org.graalvm.compiler.nodes.extended.UnsafeCopyNode; -import org.graalvm.compiler.nodes.extended.UnsafeLoadNode; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; -import org.graalvm.compiler.replacements.nodes.DirectObjectStoreNode; import org.graalvm.compiler.word.ObjectAccess; -import org.graalvm.compiler.word.Unsigned; -import org.graalvm.compiler.word.Word; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.UnsignedWord; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.JavaKind; @@ -205,7 +207,7 @@ public class UnsafeArrayCopySnippets implements Snippets { /** * For this kind, Object, we want to avoid write barriers between writes, but instead have them - * at the end of the snippet. This is done by using {@link DirectObjectStoreNode}, and rely on + * at the end of the snippet. This is done by using {@link RawStoreNode}, and rely on * {@link WriteBarrierAdditionPhase} to put write barriers after the {@link UnsafeArrayCopyNode} * with kind Object. */ @@ -218,14 +220,14 @@ public class UnsafeArrayCopySnippets implements Snippets { if (src == dest && srcPos < destPos) { // bad aliased case long start = (long) (length - 1) * scale; for (long i = start; i >= 0; i -= scale) { - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, kind, arrayLocation); - DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a, getArrayLocation(kind), kind); + Object a = RawLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, kind, arrayLocation); + RawStoreNode.storeObject(dest, arrayBaseOffset + i + (long) destPos * scale, a, kind, getArrayLocation(kind), false); } } else { long end = (long) length * scale; for (long i = 0; i < end; i += scale) { - Object a = UnsafeLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, kind, arrayLocation); - DirectObjectStoreNode.storeObject(dest, arrayBaseOffset, i + (long) destPos * scale, a, getArrayLocation(kind), kind); + Object a = RawLoadNode.load(src, arrayBaseOffset + i + (long) srcPos * scale, kind, arrayLocation); + RawStoreNode.storeObject(dest, arrayBaseOffset + i + (long) destPos * scale, a, kind, getArrayLocation(kind), false); } } } @@ -235,15 +237,15 @@ public class UnsafeArrayCopySnippets implements Snippets { int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG); int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG); - Unsigned vectorSize = Word.unsigned(VECTOR_SIZE); - Unsigned srcOffset = Word.unsigned(srcPos).shiftLeft(log2ElementSize).add(headerSize); - Unsigned destOffset = Word.unsigned(destPos).shiftLeft(log2ElementSize).add(headerSize); - Unsigned destStart = destOffset; - Unsigned destEnd = destOffset.add(Word.unsigned(length).shiftLeft(log2ElementSize)); + UnsignedWord vectorSize = WordFactory.unsigned(VECTOR_SIZE); + UnsignedWord srcOffset = WordFactory.unsigned(srcPos).shiftLeft(log2ElementSize).add(headerSize); + UnsignedWord destOffset = WordFactory.unsigned(destPos).shiftLeft(log2ElementSize).add(headerSize); + UnsignedWord destStart = destOffset; + UnsignedWord destEnd = destOffset.add(WordFactory.unsigned(length).shiftLeft(log2ElementSize)); - Unsigned destVectorEnd = null; - Unsigned nonVectorBytes = null; - Unsigned sizeInBytes = Word.unsigned(length).shiftLeft(log2ElementSize); + UnsignedWord destVectorEnd = null; + UnsignedWord nonVectorBytes = null; + UnsignedWord sizeInBytes = WordFactory.unsigned(length).shiftLeft(log2ElementSize); if (supportsUnalignedMemoryAccess) { nonVectorBytes = sizeInBytes.unsignedRemainder(vectorSize); destVectorEnd = destEnd; @@ -259,7 +261,7 @@ public class UnsafeArrayCopySnippets implements Snippets { destVectorEnd = destEnd.subtract(destEnd.unsignedRemainder(vectorSize)); } - Unsigned destNonVectorEnd = destStart.add(nonVectorBytes); + UnsignedWord destNonVectorEnd = destStart.add(nonVectorBytes); while (destOffset.belowThan(destNonVectorEnd)) { ObjectAccess.writeByte(dest, destOffset, ObjectAccess.readByte(src, srcOffset, any()), any()); destOffset = destOffset.add(1); @@ -284,8 +286,8 @@ public class UnsafeArrayCopySnippets implements Snippets { private final SnippetInfo[] arraycopySnippets; private final SnippetInfo genericPrimitiveSnippet; - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); arraycopySnippets = new SnippetInfo[JavaKind.values().length]; arraycopySnippets[JavaKind.Boolean.ordinal()] = snippet(UnsafeArrayCopySnippets.class, "arraycopyBoolean"); @@ -315,7 +317,7 @@ public class UnsafeArrayCopySnippets implements Snippets { Arguments args = new Arguments(snippet, node.graph().getGuardsStage(), tool.getLoweringStage()); node.addSnippetArguments(args); - SnippetTemplate template = template(args); + SnippetTemplate template = template(node.getDebug(), args); template.instantiate(providers.getMetaAccess(), node, DEFAULT_REPLACER, args); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java index 87ce20ab8f9..a287f15dfaf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProbabilisticProfileSnippets.java @@ -31,6 +31,7 @@ import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; @@ -46,6 +47,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -113,8 +115,8 @@ public class ProbabilisticProfileSnippets implements Snippets { private final SnippetInfo profileBackedgeWithProbability = snippet(ProbabilisticProfileSnippets.class, "profileBackedgeWithProbability"); private final SnippetInfo profileConditionalBackedgeWithProbability = snippet(ProbabilisticProfileSnippets.class, "profileConditionalBackedgeWithProbability"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); } public void lower(ProfileNode profileNode, LoweringTool tool) { @@ -140,7 +142,7 @@ public class ProbabilisticProfileSnippets implements Snippets { args.add("bci", bci); args.add("targetBci", targetBci); - SnippetTemplate template = template(args); + SnippetTemplate template = template(graph.getDebug(), args); template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args); } else if (profileNode instanceof ProfileInvokeNode) { ProfileInvokeNode profileInvokeNode = (ProfileInvokeNode) profileNode; @@ -150,7 +152,7 @@ public class ProbabilisticProfileSnippets implements Snippets { args.add("random", profileInvokeNode.getRandom()); args.addConst("freqLog", profileInvokeNode.getNotificationFreqLog()); args.addConst("probLog", profileInvokeNode.getProbabilityLog()); - SnippetTemplate template = template(args); + SnippetTemplate template = template(graph.getDebug(), args); template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args); } else { throw new GraalError("Unsupported profile node type: " + profileNode); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java index 98c5588b4d5..1c5f05e1a13 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/profiling/ProfileSnippets.java @@ -31,6 +31,7 @@ import static org.graalvm.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.DebugHandlersFactory; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; @@ -46,6 +47,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.ForeignCallNode; import org.graalvm.compiler.nodes.spi.LoweringTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.SnippetTemplate; import org.graalvm.compiler.replacements.SnippetTemplate.AbstractTemplates; import org.graalvm.compiler.replacements.SnippetTemplate.Arguments; @@ -95,8 +97,8 @@ public class ProfileSnippets implements Snippets { private final SnippetInfo profileBackedge = snippet(ProfileSnippets.class, "profileBackedge"); private final SnippetInfo profileConditionalBackedge = snippet(ProfileSnippets.class, "profileConditionalBackedge"); - public Templates(HotSpotProviders providers, TargetDescription target) { - super(providers, providers.getSnippetReflection(), target); + public Templates(OptionValues options, Iterable factories, HotSpotProviders providers, TargetDescription target) { + super(options, factories, providers, providers.getSnippetReflection(), target); } public void lower(ProfileNode profileNode, LoweringTool tool) { @@ -118,7 +120,7 @@ public class ProfileSnippets implements Snippets { args.add("bci", bci); args.add("targetBci", targetBci); - SnippetTemplate template = template(args); + SnippetTemplate template = template(graph.getDebug(), args); template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args); } else if (profileNode instanceof ProfileInvokeNode) { ProfileInvokeNode profileInvokeNode = (ProfileInvokeNode) profileNode; @@ -126,7 +128,7 @@ public class ProfileSnippets implements Snippets { Arguments args = new Arguments(profileMethodEntry, graph.getGuardsStage(), tool.getLoweringStage()); args.add("counters", counters); args.addConst("freqLog", profileInvokeNode.getNotificationFreqLog()); - SnippetTemplate template = template(args); + SnippetTemplate template = template(graph.getDebug(), args); template.instantiate(providers.getMetaAccess(), profileNode, DEFAULT_REPLACER, args); } else { throw new GraalError("Unsupported profile node type: " + profileNode); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ArrayStoreExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ArrayStoreExceptionStub.java index 9877dc7cd94..bff470d18a4 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ArrayStoreExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ArrayStoreExceptionStub.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil; import org.graalvm.compiler.hotspot.word.KlassPointer; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.Register; @@ -36,8 +37,8 @@ import jdk.vm.ci.code.Register; */ public class ArrayStoreExceptionStub extends CreateExceptionStub { - public ArrayStoreExceptionStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("createArrayStoreException", providers, linkage); + public ArrayStoreExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("createArrayStoreException", options, providers, linkage); } @Override @@ -47,7 +48,7 @@ public class ArrayStoreExceptionStub extends CreateExceptionStub { } @Snippet - private static Object createArrayStoreException(Object object, @ConstantParameter Register threadRegister) { + private static Object createArrayStoreException(@Snippet.NonNullParameter Object object, @ConstantParameter Register threadRegister) { KlassPointer klass = HotSpotReplacementsUtil.loadHub(object); return createException(threadRegister, ArrayStoreException.class, klass); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ClassCastExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ClassCastExceptionStub.java index d9a7aa18f1d..57ccd5dcefe 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ClassCastExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ClassCastExceptionStub.java @@ -29,6 +29,7 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil; import org.graalvm.compiler.hotspot.word.KlassPointer; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.Register; @@ -36,8 +37,8 @@ import jdk.vm.ci.code.Register; */ public class ClassCastExceptionStub extends CreateExceptionStub { - public ClassCastExceptionStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("createClassCastException", providers, linkage); + public ClassCastExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("createClassCastException", options, providers, linkage); } @Override @@ -47,7 +48,7 @@ public class ClassCastExceptionStub extends CreateExceptionStub { } @Snippet - private static Object createClassCastException(Object object, KlassPointer targetKlass, @ConstantParameter Register threadRegister) { + private static Object createClassCastException(@Snippet.NonNullParameter Object object, KlassPointer targetKlass, @ConstantParameter Register threadRegister) { KlassPointer objKlass = HotSpotReplacementsUtil.loadHub(object); return createException(threadRegister, ClassCastException.class, objKlass, targetKlass); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java index 64360137f71..ee73126f170 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java @@ -22,24 +22,25 @@ */ package org.graalvm.compiler.hotspot.stubs; -import static org.graalvm.compiler.core.common.LocationIdentity.any; +import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.SAFEPOINT; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.REEXECUTABLE; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; -import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; +import static org.graalvm.word.LocationIdentity.any; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; +import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; import org.graalvm.compiler.hotspot.word.KlassPointer; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.replacements.nodes.CStringConstant; import org.graalvm.compiler.word.Word; @@ -50,8 +51,8 @@ import jdk.vm.ci.code.Register; */ public class CreateExceptionStub extends SnippetStub { - protected CreateExceptionStub(String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super(snippetMethodName, providers, linkage); + protected CreateExceptionStub(String snippetMethodName, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super(snippetMethodName, options, providers, linkage); } @Fold diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/DeoptimizationStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/DeoptimizationStub.java deleted file mode 100644 index acfb4e151e6..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/DeoptimizationStub.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.stubs; - -import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; -import static org.graalvm.compiler.hotspot.HotSpotBackend.UNPACK_FRAMES; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.nodes.DeoptimizationFetchUnrollInfoCallNode.fetchUnrollInfo; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.pageSize; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeRegisterAsWord; -import static org.graalvm.compiler.hotspot.stubs.UncommonTrapStub.STACK_BANG_LOCATION; - -import org.graalvm.compiler.api.replacements.Fold; -import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; -import org.graalvm.compiler.api.replacements.Snippet; -import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.asm.NumUtil; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node.ConstantNodeParameter; -import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.EnterUnpackFramesStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveCurrentStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveDeoptimizedStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.LeaveUnpackFramesStackFrameNode; -import org.graalvm.compiler.hotspot.nodes.PushInterpreterFrameNode; -import org.graalvm.compiler.hotspot.nodes.SaveAllRegistersNode; -import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.TargetDescription; - -/** - * Deoptimization stub. - * - * This is the entry point for code which is returning to a de-optimized frame. - * - * The steps taken by this frame are as follows: - * - *
    11. push a dummy "register_save" and save the return values (O0, O1, F0/F1, G1) and all - * potentially live registers (at a pollpoint many registers can be live). - * - *
    12. call the C routine: Deoptimization::fetch_unroll_info (this function returns information - * about the number and size of interpreter frames which are equivalent to the frame which is being - * deoptimized) - * - *
    13. deallocate the unpack frame, restoring only results values. Other volatile registers will now - * be captured in the vframeArray as needed. - * - *
    14. deallocate the deoptimization frame - * - *
    15. in a loop using the information returned in the previous step push new interpreter frames - * (take care to propagate the return values through each new frame pushed) - * - *
    16. create a dummy "unpack_frame" and save the return values (O0, O1, F0) - * - *
    17. call the C routine: Deoptimization::unpack_frames (this function lays out values on the - * interpreter frame which was just created) - * - *
    18. deallocate the dummy unpack_frame - * - *
    19. ensure that all the return values are correctly set and then do a return to the interpreter - * entry point - * - *

      - * ATTENTION: We cannot do any complicated operations e.g. logging via printf in this snippet - * because we change the current stack layout and so the code is very sensitive to register - * allocation. - */ -public class DeoptimizationStub extends SnippetStub { - - private final TargetDescription target; - - public DeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(DeoptimizationStub.class, "deoptimizationHandler", providers, linkage); - this.target = target; - assert PreferGraalStubs.getValue(); - } - - @Override - public boolean preservesRegisters() { - return false; - } - - @Override - protected Object getConstantParameterValue(int index, String name) { - switch (index) { - case 0: - return providers.getRegisters().getThreadRegister(); - case 1: - return providers.getRegisters().getStackPointerRegister(); - default: - throw GraalError.shouldNotReachHere("unknown parameter " + name + " at index " + index); - } - } - - /** - * Deoptimization handler for normal deoptimization - * {@link GraalHotSpotVMConfig#deoptimizationUnpackDeopt}. - */ - @Snippet - private static void deoptimizationHandler(@ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister) { - final Word thread = registerAsWord(threadRegister); - final long registerSaver = SaveAllRegistersNode.saveAllRegisters(); - - final Word unrollBlock = fetchUnrollInfo(registerSaver, deoptimizationUnpackDeopt(INJECTED_VMCONFIG)); - - deoptimizationCommon(stackPointerRegister, thread, registerSaver, unrollBlock); - } - - static void deoptimizationCommon(Register stackPointerRegister, final Word thread, final long registerSaver, final Word unrollBlock) { - // Pop all the frames we must move/replace. - // - // Frame picture (youngest to oldest) - // 1: self-frame - // 2: deoptimizing frame - // 3: caller of deoptimizing frame (could be compiled/interpreted). - - // Pop self-frame. - LeaveCurrentStackFrameNode.leaveCurrentStackFrame(registerSaver); - - // Load the initial info we should save (e.g. frame pointer). - final Word initialInfo = unrollBlock.readWord(deoptimizationUnrollBlockInitialInfoOffset(INJECTED_VMCONFIG)); - - // Pop deoptimized frame. - final int sizeOfDeoptimizedFrame = unrollBlock.readInt(deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset(INJECTED_VMCONFIG)); - LeaveDeoptimizedStackFrameNode.leaveDeoptimizedStackFrame(sizeOfDeoptimizedFrame, initialInfo); - - /* - * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for - * total size of the interpreter frames plus shadow page size. Bang one page at a time - * because large sizes can bang beyond yellow and red zones. - * - * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository. - */ - final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset(INJECTED_VMCONFIG)); - final int bangPages = NumUtil.roundUp(totalFrameSizes, pageSize()) / pageSize() + stackShadowPages(INJECTED_VMCONFIG); - Word stackPointer = readRegister(stackPointerRegister); - - for (int i = 1; i < bangPages; i++) { - stackPointer.writeInt((-i * pageSize()) + stackBias(INJECTED_VMCONFIG), 0, STACK_BANG_LOCATION); - } - - // Load number of interpreter frames. - final int numberOfFrames = unrollBlock.readInt(deoptimizationUnrollBlockNumberOfFramesOffset(INJECTED_VMCONFIG)); - - // Load address of array of frame sizes. - final Word frameSizes = unrollBlock.readWord(deoptimizationUnrollBlockFrameSizesOffset(INJECTED_VMCONFIG)); - - // Load address of array of frame PCs. - final Word framePcs = unrollBlock.readWord(deoptimizationUnrollBlockFramePcsOffset(INJECTED_VMCONFIG)); - - /* - * Get the current stack pointer (sender's original SP) before adjustment so that we can - * save it in the skeletal interpreter frame. - */ - Word senderSp = readRegister(stackPointerRegister); - - // Adjust old interpreter frame to make space for new frame's extra Java locals. - final int callerAdjustment = unrollBlock.readInt(deoptimizationUnrollBlockCallerAdjustmentOffset(INJECTED_VMCONFIG)); - writeRegister(stackPointerRegister, readRegister(stackPointerRegister).subtract(callerAdjustment)); - - for (int i = 0; i < numberOfFrames; i++) { - final Word frameSize = frameSizes.readWord(i * wordSize()); - final Word framePc = framePcs.readWord(i * wordSize()); - - // Push an interpreter frame onto the stack. - PushInterpreterFrameNode.pushInterpreterFrame(frameSize, framePc, senderSp, initialInfo); - - // Get the current stack pointer (sender SP) and pass it to next frame. - senderSp = readRegister(stackPointerRegister); - } - - // Get final return address. - final Word framePc = framePcs.readWord(numberOfFrames * wordSize()); - - /* - * Enter a frame to call out to unpack frames. Since we changed the stack pointer to an - * unknown alignment we need to align it here before calling C++ code. - */ - final Word senderFp = initialInfo; - EnterUnpackFramesStackFrameNode.enterUnpackFramesStackFrame(framePc, senderSp, senderFp, registerSaver); - - final int mode = unrollBlock.readInt(deoptimizationUnrollBlockUnpackKindOffset(INJECTED_VMCONFIG)); - unpackFrames(UNPACK_FRAMES, thread, mode); - - LeaveUnpackFramesStackFrameNode.leaveUnpackFramesStackFrame(registerSaver); - } - - /** - * Reads the value of the passed register as a Word. - */ - private static Word readRegister(Register register) { - return registerAsWord(register, false, false); - } - - /** - * Writes the value of the passed register. - * - * @param value value the register should be set to - */ - private static void writeRegister(Register register, Word value) { - writeRegisterAsWord(register, value); - } - - @Fold - static int stackShadowPages(@InjectedParameter GraalHotSpotVMConfig config) { - return config.useStackBanging ? config.stackShadowPages : 0; - } - - /** - * Returns the stack bias for the host architecture. - * - * @deprecated This method should go away as soon as JDK-8032410 hits the Graal repository. - * - * @return stack bias - */ - @Deprecated - @Fold - static int stackBias(@InjectedParameter GraalHotSpotVMConfig config) { - return config.stackBias; - } - - @Fold - static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; - } - - @Fold - static int deoptimizationUnrollBlockCallerAdjustmentOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockCallerAdjustmentOffset; - } - - @Fold - static int deoptimizationUnrollBlockNumberOfFramesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockNumberOfFramesOffset; - } - - @Fold - static int deoptimizationUnrollBlockTotalFrameSizesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockTotalFrameSizesOffset; - } - - @Fold - static int deoptimizationUnrollBlockUnpackKindOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockUnpackKindOffset; - } - - @Fold - static int deoptimizationUnrollBlockFrameSizesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockFrameSizesOffset; - } - - @Fold - static int deoptimizationUnrollBlockFramePcsOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockFramePcsOffset; - } - - @Fold - static int deoptimizationUnrollBlockInitialInfoOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockInitialInfoOffset; - } - - @Fold - static int deoptimizationUnpackDeopt(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnpackDeopt; - } - - @Fold - static int deoptimizationUnpackUncommonTrap(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnpackUncommonTrap; - } - - @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) - public static native int unpackFrames(@ConstantNodeParameter ForeignCallDescriptor unpackFrames, Word thread, int mode); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java index bd435f90a32..58077ba3900 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java @@ -41,6 +41,7 @@ import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -48,7 +49,9 @@ import org.graalvm.compiler.hotspot.HotSpotBackend; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.Register; @@ -62,8 +65,8 @@ import jdk.vm.ci.code.Register; */ public class ExceptionHandlerStub extends SnippetStub { - public ExceptionHandlerStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("exceptionHandler", providers, linkage); + public ExceptionHandlerStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("exceptionHandler", options, providers, linkage); } /** @@ -78,18 +81,21 @@ public class ExceptionHandlerStub extends SnippetStub { @Override protected Object getConstantParameterValue(int index, String name) { - assert index == 2; - return providers.getRegisters().getThreadRegister(); + if (index == 2) { + return providers.getRegisters().getThreadRegister(); + } + assert index == 3; + return options; } @Snippet - private static void exceptionHandler(Object exception, Word exceptionPc, @ConstantParameter Register threadRegister) { + private static void exceptionHandler(Object exception, Word exceptionPc, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) { Word thread = registerAsWord(threadRegister); checkNoExceptionInThread(thread, assertionsEnabled(INJECTED_VMCONFIG)); checkExceptionNotNull(assertionsEnabled(INJECTED_VMCONFIG), exception); writeExceptionOop(thread, exception); writeExceptionPc(thread, exceptionPc); - if (logging()) { + if (logging(options)) { printf("handling exception %p (", Word.objectToTrackedPointer(exception).rawValue()); decipher(Word.objectToTrackedPointer(exception).rawValue()); printf(") at %p (", exceptionPc.rawValue()); @@ -102,7 +108,7 @@ public class ExceptionHandlerStub extends SnippetStub { Word handlerPc = exceptionHandlerForPc(EXCEPTION_HANDLER_FOR_PC, thread); - if (logging()) { + if (logging(options)) { printf("handler for exception %p at %p is at %p (", Word.objectToTrackedPointer(exception).rawValue(), exceptionPc.rawValue(), handlerPc.rawValue()); decipher(handlerPc.rawValue()); printf(")\n"); @@ -122,7 +128,7 @@ public class ExceptionHandlerStub extends SnippetStub { // This thread-local is only cleared in DEBUG builds of the VM // (see OptoRuntime::generate_exception_blob) Word currentExceptionPc = readExceptionPc(thread); - if (currentExceptionPc.notEqual(Word.zero())) { + if (currentExceptionPc.notEqual(WordFactory.zero())) { fatal("exception PC in thread must be zero, not %p", currentExceptionPc.rawValue()); } } @@ -136,27 +142,22 @@ public class ExceptionHandlerStub extends SnippetStub { } @Fold - static boolean logging() { - return StubOptions.TraceExceptionHandlerStub.getValue(); + static boolean logging(OptionValues options) { + return StubOptions.TraceExceptionHandlerStub.getValue(options); } /** - * Determines if either Java assertions are enabled for {@link ExceptionHandlerStub} or if this - * is a HotSpot build where the ASSERT mechanism is enabled. - *

      - * This first check relies on the per-class assertion status which is why this method must be in - * this class. + * Determines if either Java assertions are enabled for Graal or if this is a HotSpot build + * where the ASSERT mechanism is enabled. */ @Fold @SuppressWarnings("all") static boolean assertionsEnabled(@InjectedParameter GraalHotSpotVMConfig config) { - boolean enabled = false; - assert enabled = true; - return enabled || cAssertionsEnabled(config); + return Assertions.assertionsEnabled() || cAssertionsEnabled(config); } public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_PC = newDescriptor(ExceptionHandlerStub.class, "exceptionHandlerForPc", Word.class, Word.class); - @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = StubForeignCallNode.class) public static native Word exceptionHandlerForPc(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForPc, Word thread); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java index ef51bbdf472..d817dd3c03b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java @@ -22,19 +22,19 @@ */ package org.graalvm.compiler.hotspot.stubs; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; -import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCall; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.JavaCallee; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS; +import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.PRESERVES_REGISTERS; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.LIRKind; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.JavaMethodContext; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition; @@ -47,15 +47,18 @@ import org.graalvm.compiler.nodes.InvokeNode; import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.ReturnNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.replacements.GraphKit; import org.graalvm.compiler.replacements.nodes.ReadRegisterNode; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.WordTypes; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; import jdk.vm.ci.hotspot.HotSpotSignature; +import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaMethod; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.MetaAccessProvider; @@ -99,9 +102,11 @@ public class ForeignCallStub extends Stub { * be re-executed. * @param killedLocations the memory locations killed by the stub call */ - public ForeignCallStub(HotSpotJVMCIRuntimeProvider runtime, HotSpotProviders providers, long address, ForeignCallDescriptor descriptor, boolean prependThread, Transition transition, - boolean reexecutable, LocationIdentity... killedLocations) { - super(providers, HotSpotForeignCallLinkageImpl.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getWordTypes(), providers.getForeignCalls(), descriptor, 0L, + public ForeignCallStub(OptionValues options, HotSpotJVMCIRuntimeProvider runtime, HotSpotProviders providers, long address, ForeignCallDescriptor descriptor, boolean prependThread, + Transition transition, + boolean reexecutable, + LocationIdentity... killedLocations) { + super(options, providers, HotSpotForeignCallLinkageImpl.create(providers.getMetaAccess(), providers.getCodeCache(), providers.getWordTypes(), providers.getForeignCalls(), descriptor, 0L, PRESERVES_REGISTERS, JavaCall, JavaCallee, transition, reexecutable, killedLocations)); this.jvmciRuntime = runtime; this.prependThread = prependThread; @@ -219,12 +224,11 @@ public class ForeignCallStub extends Stub { * %r15 on AMD64) and is only prepended if {@link #prependThread} is true. */ @Override - protected StructuredGraph getGraph(CompilationIdentifier compilationId) { + protected StructuredGraph getGraph(DebugContext debug, CompilationIdentifier compilationId) { WordTypes wordTypes = providers.getWordTypes(); Class[] args = linkage.getDescriptor().getArgumentTypes(); boolean isObjectResult = !LIRKind.isValue(linkage.getOutgoingCallingConvention().getReturn()); - - StructuredGraph graph = new StructuredGraph(toString(), null, AllowAssumptions.NO, compilationId); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).name(toString()).compilationId(compilationId).build(); graph.disableUnsafeAccessTracking(); GraphKit kit = new GraphKit(graph, providers, wordTypes, providers.getGraphBuilderPlugins()); @@ -239,15 +243,13 @@ public class ForeignCallStub extends Stub { } kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result)); - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Initial stub graph"); - } + debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Initial stub graph"); kit.inlineInvokes(); - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Stub graph before compilation"); - } + new RemoveValueProxyPhase().apply(graph); + + debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Stub graph before compilation"); return graph; } @@ -265,13 +267,14 @@ public class ForeignCallStub extends Stub { } private StubForeignCallNode createTargetCall(GraphKit kit, ParameterNode[] params, ReadRegisterNode thread) { + Stamp stamp = StampFactory.forKind(JavaKind.fromJavaClass(target.getDescriptor().getResultType())); if (prependThread) { ValueNode[] targetArguments = new ValueNode[1 + params.length]; targetArguments[0] = thread; System.arraycopy(params, 0, targetArguments, 1, params.length); - return kit.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), targetArguments)); + return kit.append(new StubForeignCallNode(providers.getForeignCalls(), stamp, target.getDescriptor(), targetArguments)); } else { - return kit.append(new StubForeignCallNode(providers.getForeignCalls(), target.getDescriptor(), params)); + return kit.append(new StubForeignCallNode(providers.getForeignCalls(), stamp, target.getDescriptor(), params)); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java index c30dda95f4c..d7018a1ef75 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java @@ -31,7 +31,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperHeaderSizeShift; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeMask; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeShift; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadKlassLayoutHelperIntrinsic; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readLayoutHelper; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; import static org.graalvm.compiler.hotspot.replacements.NewObjectSnippets.MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH; @@ -57,7 +57,9 @@ import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.Register; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; @@ -70,8 +72,8 @@ import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; */ public class NewArrayStub extends SnippetStub { - public NewArrayStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("newArray", providers, linkage); + public NewArrayStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("newArray", options, providers, linkage); } @Override @@ -81,14 +83,16 @@ public class NewArrayStub extends SnippetStub { Object[] args = new Object[count]; assert checkConstArg(3, "intArrayHub"); assert checkConstArg(4, "threadRegister"); + assert checkConstArg(5, "options"); args[3] = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), intArrayType.klass(), null); args[4] = providers.getRegisters().getThreadRegister(); + args[5] = options; return args; } @Fold - static boolean logging() { - return StubOptions.TraceNewArrayStub.getValue(); + static boolean logging(OptionValues options) { + return StubOptions.TraceNewArrayStub.getValue(options); } /** @@ -101,13 +105,14 @@ public class NewArrayStub extends SnippetStub { * @param intArrayHub the hub for {@code int[].class} */ @Snippet - private static Object newArray(KlassPointer hub, int length, boolean fillContents, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister) { - int layoutHelper = loadKlassLayoutHelperIntrinsic(hub); + private static Object newArray(KlassPointer hub, int length, boolean fillContents, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister, + @ConstantParameter OptionValues options) { + int layoutHelper = readLayoutHelper(hub); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG); int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG); int elementKind = (layoutHelper >> layoutHelperElementTypeShift(INJECTED_VMCONFIG)) & layoutHelperElementTypeMask(INJECTED_VMCONFIG); int sizeInBytes = computeArrayAllocationSize(length, wordSize(), headerSize, log2ElementSize); - if (logging()) { + if (logging(options)) { printf("newArray: element kind %d\n", elementKind); printf("newArray: array length %d\n", length); printf("newArray: array size %d\n", sizeInBytes); @@ -118,16 +123,16 @@ public class NewArrayStub extends SnippetStub { Word thread = registerAsWord(threadRegister); boolean inlineContiguousAllocationSupported = GraalHotSpotVMConfigNode.inlineContiguousAllocationSupported(); if (inlineContiguousAllocationSupported && length >= 0 && length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) { - Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging()); + Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging(options)); if (memory.notEqual(0)) { - if (logging()) { + if (logging(options)) { printf("newArray: allocated new array at %p\n", memory.rawValue()); } return verifyObject( - formatArray(hub, sizeInBytes, length, headerSize, memory, Word.unsigned(arrayPrototypeMarkWord(INJECTED_VMCONFIG)), fillContents, false, false)); + formatArray(hub, sizeInBytes, length, headerSize, memory, WordFactory.unsigned(arrayPrototypeMarkWord(INJECTED_VMCONFIG)), fillContents, false, null)); } } - if (logging()) { + if (logging(options)) { printf("newArray: calling new_array_c\n"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java index b6a64dc4b8a..91a5acab1f1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java @@ -23,7 +23,6 @@ package org.graalvm.compiler.hotspot.stubs; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; -import static org.graalvm.compiler.hotspot.nodes.DirectCompareAndSwapNode.compareAndSwap; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HEAP_END_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HEAP_TOP_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION; @@ -37,7 +36,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil. import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getAndClearObjectResult; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.initializeTlab; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.isInstanceKlassFullyInitialized; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadKlassLayoutHelperIntrinsic; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readLayoutHelper; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.log2WordSize; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.prototypeMarkWordOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readTlabEnd; @@ -79,8 +78,9 @@ import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp; import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.memory.address.RawAddressNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; +import org.graalvm.word.WordFactory; import jdk.vm.ci.code.Register; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; @@ -94,8 +94,8 @@ import jdk.vm.ci.meta.JavaKind; */ public class NewInstanceStub extends SnippetStub { - public NewInstanceStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("newInstance", providers, linkage); + public NewInstanceStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("newInstance", options, providers, linkage); } @Override @@ -105,8 +105,10 @@ public class NewInstanceStub extends SnippetStub { Object[] args = new Object[count]; assert checkConstArg(1, "intArrayHub"); assert checkConstArg(2, "threadRegister"); + assert checkConstArg(3, "options"); args[1] = ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), intArrayType.klass(), null); args[2] = providers.getRegisters().getThreadRegister(); + args[3] = options; return args; } @@ -122,12 +124,12 @@ public class NewInstanceStub extends SnippetStub { writeTlabTop(thread, newTop); return top; } - return Word.zero(); + return WordFactory.zero(); } @Fold - static boolean logging() { - return StubOptions.TraceNewInstanceStub.getValue(); + static boolean logging(OptionValues options) { + return StubOptions.TraceNewInstanceStub.getValue(options); } /** @@ -138,17 +140,17 @@ public class NewInstanceStub extends SnippetStub { * @param intArrayHub the hub for {@code int[].class} */ @Snippet - private static Object newInstance(KlassPointer hub, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister) { + private static Object newInstance(KlassPointer hub, @ConstantParameter KlassPointer intArrayHub, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) { /* * The type is known to be an instance so Klass::_layout_helper is the instance size as a * raw number */ - int sizeInBytes = loadKlassLayoutHelperIntrinsic(hub); Word thread = registerAsWord(threadRegister); boolean inlineContiguousAllocationSupported = GraalHotSpotVMConfigNode.inlineContiguousAllocationSupported(); - if (!forceSlowPath() && inlineContiguousAllocationSupported) { + if (!forceSlowPath(options) && inlineContiguousAllocationSupported) { if (isInstanceKlassFullyInitialized(hub)) { - Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging()); + int sizeInBytes = readLayoutHelper(hub); + Word memory = refillAllocate(thread, intArrayHub, sizeInBytes, logging(options)); if (memory.notEqual(0)) { Word prototypeMarkWord = hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION); NewObjectSnippets.formatObjectForStub(hub, sizeInBytes, memory, prototypeMarkWord); @@ -157,7 +159,7 @@ public class NewInstanceStub extends SnippetStub { } } - if (logging()) { + if (logging(options)) { printf("newInstance: calling new_instance_c\n"); } @@ -173,19 +175,19 @@ public class NewInstanceStub extends SnippetStub { * @param sizeInBytes the size of the allocation * @param log specifies if logging is enabled * - * @return the newly allocated, uninitialized chunk of memory, or {@link Word#zero()} if the - * operation was unsuccessful + * @return the newly allocated, uninitialized chunk of memory, or {@link WordFactory#zero()} if + * the operation was unsuccessful */ static Word refillAllocate(Word thread, KlassPointer intArrayHub, int sizeInBytes, boolean log) { // If G1 is enabled, the "eden" allocation space is not the same always // and therefore we have to go to slowpath to allocate a new TLAB. if (useG1GC(INJECTED_VMCONFIG)) { - return Word.zero(); + return WordFactory.zero(); } if (!useTLAB(INJECTED_VMCONFIG)) { - return edenAllocate(Word.unsigned(sizeInBytes), log); + return edenAllocate(WordFactory.unsigned(sizeInBytes), log); } - Word intArrayMarkWord = Word.unsigned(tlabIntArrayMarkWord(INJECTED_VMCONFIG)); + Word intArrayMarkWord = WordFactory.unsigned(tlabIntArrayMarkWord(INJECTED_VMCONFIG)); int alignmentReserveInBytes = tlabAlignmentReserveInHeapWords(INJECTED_VMCONFIG) * wordSize(); Word top = readTlabTop(thread); @@ -229,7 +231,7 @@ public class NewInstanceStub extends SnippetStub { // an int int tlabFreeSpaceInInts = (int) tlabFreeSpaceInBytes >>> 2; int length = ((alignmentReserveInBytes - headerSize) >>> 2) + tlabFreeSpaceInInts; - NewObjectSnippets.formatArray(intArrayHub, 0, length, headerSize, top, intArrayMarkWord, false, false, false); + NewObjectSnippets.formatArray(intArrayHub, 0, length, headerSize, top, intArrayMarkWord, false, false, null); long allocated = thread.readLong(threadAllocatedBytesOffset(INJECTED_VMCONFIG), TLAB_THREAD_ALLOCATED_BYTES_LOCATION); allocated = allocated + top.subtract(readTlabStart(thread)).rawValue(); @@ -247,7 +249,7 @@ public class NewInstanceStub extends SnippetStub { return NewInstanceStub.allocate(thread, sizeInBytes); } else { - return Word.zero(); + return WordFactory.zero(); } } else { // Retain TLAB @@ -262,7 +264,7 @@ public class NewInstanceStub extends SnippetStub { TLAB_SLOW_ALLOCATIONS_LOCATION); } - return edenAllocate(Word.unsigned(sizeInBytes), log); + return edenAllocate(WordFactory.unsigned(sizeInBytes), log); } } @@ -271,36 +273,35 @@ public class NewInstanceStub extends SnippetStub { * * @param sizeInBytes the size of the chunk to allocate * @param log specifies if logging is enabled - * @return the allocated chunk or {@link Word#zero()} if allocation fails + * @return the allocated chunk or {@link WordFactory#zero()} if allocation fails */ public static Word edenAllocate(Word sizeInBytes, boolean log) { final long heapTopRawAddress = GraalHotSpotVMConfigNode.heapTopAddress(); final long heapEndRawAddress = GraalHotSpotVMConfigNode.heapEndAddress(); - Word heapTopAddress = Word.unsigned(heapTopRawAddress); - Word heapEndAddress = Word.unsigned(heapEndRawAddress); + Word heapTopAddress = WordFactory.unsigned(heapTopRawAddress); + Word heapEndAddress = WordFactory.unsigned(heapEndRawAddress); while (true) { Word heapTop = heapTopAddress.readWord(0, HEAP_TOP_LOCATION); Word newHeapTop = heapTop.add(sizeInBytes); if (newHeapTop.belowOrEqual(heapTop)) { - return Word.zero(); + return WordFactory.zero(); } Word heapEnd = heapEndAddress.readWord(0, HEAP_END_LOCATION); if (newHeapTop.aboveThan(heapEnd)) { - return Word.zero(); + return WordFactory.zero(); } - - if (compareAndSwap(RawAddressNode.address(heapTopAddress), heapTop, newHeapTop, HEAP_TOP_LOCATION).equal(heapTop)) { + if (heapTopAddress.logicCompareAndSwapWord(0, heapTop, newHeapTop, HEAP_TOP_LOCATION)) { return heapTop; } } } @Fold - static boolean forceSlowPath() { - return StubOptions.ForceUseOfNewInstanceStub.getValue(); + static boolean forceSlowPath(OptionValues options) { + return StubOptions.ForceUseOfNewInstanceStub.getValue(options); } public static final ForeignCallDescriptor NEW_INSTANCE_C = newDescriptor(NewInstanceStub.class, "newInstanceC", void.class, Word.class, KlassPointer.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NullPointerExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NullPointerExceptionStub.java index b5ba143de37..662bce4c731 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NullPointerExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NullPointerExceptionStub.java @@ -27,6 +27,7 @@ import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; import jdk.vm.ci.code.Register; @@ -35,8 +36,8 @@ import jdk.vm.ci.code.Register; */ public class NullPointerExceptionStub extends CreateExceptionStub { - public NullPointerExceptionStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("createNullPointerException", providers, linkage); + public NullPointerExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("createNullPointerException", options, providers, linkage); } @Override diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java index 095680062ee..c162328ae94 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/OutOfBoundsExceptionStub.java @@ -28,6 +28,7 @@ import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.AllocaNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; import jdk.vm.ci.code.Register; @@ -37,8 +38,8 @@ import jdk.vm.ci.code.Register; */ public class OutOfBoundsExceptionStub extends CreateExceptionStub { - public OutOfBoundsExceptionStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("createOutOfBoundsException", providers, linkage); + public OutOfBoundsExceptionStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("createOutOfBoundsException", options, providers, linkage); } private static final int MAX_INT_STRING_SIZE = Integer.toString(Integer.MIN_VALUE).length(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java index b645d8944d2..658c3ce30fb 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/SnippetStub.java @@ -22,31 +22,34 @@ */ package org.graalvm.compiler.hotspot.stubs; -import static org.graalvm.compiler.nodes.StructuredGraph.NO_PROFILING_INFO; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import java.lang.reflect.Method; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.bytecode.BytecodeProvider; +import org.graalvm.compiler.core.common.CompilationIdentifier; +import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.java.GraphBuilderPhase; +import org.graalvm.compiler.nodes.ParameterNode; import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext; import org.graalvm.compiler.nodes.spi.LoweringTool; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.common.LoweringPhase; +import org.graalvm.compiler.phases.common.RemoveValueProxyPhase; import org.graalvm.compiler.phases.tiers.PhaseContext; import org.graalvm.compiler.replacements.ConstantBindingParameterPlugin; import org.graalvm.compiler.replacements.SnippetTemplate; @@ -71,8 +74,8 @@ public abstract class SnippetStub extends Stub implements Snippets { * this object * @param linkage linkage details for a call to the stub */ - public SnippetStub(String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - this(null, snippetMethodName, providers, linkage); + public SnippetStub(String snippetMethodName, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + this(null, snippetMethodName, options, providers, linkage); } /** @@ -84,24 +87,15 @@ public abstract class SnippetStub extends Stub implements Snippets { * {@code snippetDeclaringClass} * @param linkage linkage details for a call to the stub */ - public SnippetStub(Class snippetDeclaringClass, String snippetMethodName, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super(providers, linkage); + public SnippetStub(Class snippetDeclaringClass, String snippetMethodName, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super(options, providers, linkage); Method javaMethod = SnippetTemplate.AbstractTemplates.findMethod(snippetDeclaringClass == null ? getClass() : snippetDeclaringClass, snippetMethodName, null); this.method = providers.getMetaAccess().lookupJavaMethod(javaMethod); } - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean enabled = false; - assert enabled = true; - return enabled; - } - - public static final ThreadLocal SnippetGraphUnderConstruction = assertionsEnabled() ? new ThreadLocal<>() : null; - @Override @SuppressWarnings("try") - protected StructuredGraph getGraph(CompilationIdentifier compilationId) { + protected StructuredGraph getGraph(DebugContext debug, CompilationIdentifier compilationId) { Plugins defaultPlugins = providers.getGraphBuilderPlugins(); MetaAccessProvider metaAccess = providers.getMetaAccess(); SnippetReflectionProvider snippetReflection = providers.getSnippetReflection(); @@ -112,41 +106,41 @@ public abstract class SnippetStub extends Stub implements Snippets { // Stubs cannot have optimistic assumptions since they have // to be valid for the entire run of the VM. - final StructuredGraph graph = new StructuredGraph(method, AllowAssumptions.NO, NO_PROFILING_INFO, compilationId); - try (Scope outer = Debug.scope("SnippetStub", graph)) { + final StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).compilationId(compilationId).build(); + try (DebugContext.Scope outer = debug.scope("SnippetStub", graph)) { graph.disableUnsafeAccessTracking(); - if (SnippetGraphUnderConstruction != null) { - assert SnippetGraphUnderConstruction.get() == null : SnippetGraphUnderConstruction.get().toString() + " " + graph; - SnippetGraphUnderConstruction.set(graph); - } + IntrinsicContext initialIntrinsicContext = new IntrinsicContext(method, method, getReplacementsBytecodeProvider(), INLINE_AFTER_PARSING); + GraphBuilderPhase.Instance instance = new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), + providers.getConstantReflection(), providers.getConstantFieldProvider(), + config, OptimisticOptimizations.NONE, + initialIntrinsicContext); + instance.apply(graph); - try { - IntrinsicContext initialIntrinsicContext = new IntrinsicContext(method, method, providers.getReplacements().getReplacementBytecodeProvider(), INLINE_AFTER_PARSING); - GraphBuilderPhase.Instance instance = new GraphBuilderPhase.Instance(metaAccess, providers.getStampProvider(), - providers.getConstantReflection(), providers.getConstantFieldProvider(), - config, OptimisticOptimizations.NONE, - initialIntrinsicContext); - instance.apply(graph); - - } finally { - if (SnippetGraphUnderConstruction != null) { - SnippetGraphUnderConstruction.set(null); + for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) { + int index = param.index(); + if (method.getParameterAnnotation(NonNullParameter.class, index) != null) { + param.setStamp(param.stamp().join(StampFactory.objectNonNull())); } } + new RemoveValueProxyPhase().apply(graph); graph.setGuardsStage(GuardsStage.FLOATING_GUARDS); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); PhaseContext context = new PhaseContext(providers); canonicalizer.apply(graph, context); new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } return graph; } + protected BytecodeProvider getReplacementsBytecodeProvider() { + return providers.getReplacements().getDefaultReplacementBytecodeProvider(); + } + protected boolean checkConstArg(int index, String expectedName) { assert method.getParameterAnnotation(ConstantParameter.class, index) != null : String.format("parameter %d of %s is expected to be constant", index, method.format("%H.%n(%p)")); LocalVariableTable lvt = method.getLocalVariableTable(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java index 8857bd417a6..ca82512a38a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java @@ -22,24 +22,23 @@ */ package org.graalvm.compiler.hotspot.stubs; +import static java.util.Collections.singletonList; import static org.graalvm.compiler.core.GraalCompiler.emitBackEnd; import static org.graalvm.compiler.core.GraalCompiler.emitFrontEnd; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM; +import static org.graalvm.compiler.debug.DebugOptions.DebugStubsAndSnippets; import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER; +import static org.graalvm.util.CollectionsUtil.allMatch; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; import java.util.ListIterator; -import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.target.Backend; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; -import org.graalvm.compiler.debug.internal.DebugScope; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Description; import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; @@ -50,9 +49,12 @@ import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext; import org.graalvm.compiler.lir.profiling.MoveProfilingPhase; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.Suites; +import org.graalvm.compiler.printer.GraalDebugHandlersFactory; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.InstalledCode; @@ -77,8 +79,6 @@ import jdk.vm.ci.meta.TriState; */ public abstract class Stub { - private static final List stubs = new ArrayList<>(); - /** * The linkage information for a call to this stub from compiled code. */ @@ -92,11 +92,21 @@ public abstract class Stub { /** * The registers destroyed by this stub (from the caller's perspective). */ - private Set destroyedCallerRegisters; + private EconomicSet destroyedCallerRegisters; - public void initDestroyedCallerRegisters(Set registers) { + private static boolean checkRegisterSetEquivalency(EconomicSet a, EconomicSet b) { + if (a == b) { + return true; + } + if (a.size() != b.size()) { + return false; + } + return allMatch(a, e -> b.contains(e)); + } + + public void initDestroyedCallerRegisters(EconomicSet registers) { assert registers != null; - assert destroyedCallerRegisters == null || registers.equals(destroyedCallerRegisters) : "cannot redefine"; + assert destroyedCallerRegisters == null || checkRegisterSetEquivalency(registers, destroyedCallerRegisters) : "cannot redefine"; destroyedCallerRegisters = registers; } @@ -104,7 +114,7 @@ public abstract class Stub { * Gets the registers destroyed by this stub from a caller's perspective. These are the * temporaries of this stub and must thus be caller saved by a callers of this stub. */ - public Set getDestroyedCallerRegisters() { + public EconomicSet getDestroyedCallerRegisters() { assert destroyedCallerRegisters != null : "not yet initialized"; return destroyedCallerRegisters; } @@ -117,6 +127,7 @@ public abstract class Stub { return true; } + protected final OptionValues options; protected final HotSpotProviders providers; /** @@ -124,17 +135,10 @@ public abstract class Stub { * * @param linkage linkage details for a call to the stub */ - public Stub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + public Stub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { this.linkage = linkage; + this.options = options; this.providers = providers; - stubs.add(this); - } - - /** - * Gets an immutable view of all stubs that have been created. - */ - public static Collection getStubs() { - return Collections.unmodifiableList(stubs); } /** @@ -153,7 +157,7 @@ public abstract class Stub { * * @param compilationId unique compilation id for the stub */ - protected abstract StructuredGraph getGraph(CompilationIdentifier compilationId); + protected abstract StructuredGraph getGraph(DebugContext debug, CompilationIdentifier compilationId); @Override public String toString() { @@ -170,37 +174,50 @@ public abstract class Stub { */ protected abstract Object debugScopeContext(); + private static final AtomicInteger nextStubId = new AtomicInteger(); + + private DebugContext openDebugContext(DebugContext outer) { + if (DebugStubsAndSnippets.getValue(options)) { + Description description = new Description(linkage, "Stub_" + nextStubId.incrementAndGet()); + return DebugContext.create(options, description, outer.getGlobalMetrics(), DEFAULT_LOG_STREAM, singletonList(new GraalDebugHandlersFactory(providers.getSnippetReflection()))); + } + return DebugContext.DISABLED; + } + /** * Gets the code for this stub, compiling it first if necessary. */ @SuppressWarnings("try") public synchronized InstalledCode getCode(final Backend backend) { if (code == null) { - try (Scope d = Debug.sandbox("CompilingStub", DebugScope.getConfig(), providers.getCodeCache(), debugScopeContext())) { - CodeCacheProvider codeCache = providers.getCodeCache(); - CompilationResult compResult = buildCompilationResult(backend); - try (Scope s = Debug.scope("CodeInstall", compResult)) { - assert destroyedCallerRegisters != null; - // Add a GeneratePIC check here later, we don't want to install - // code if we don't have a corresponding VM global symbol. - HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(null, null, compResult); - code = codeCache.installCode(null, compiledCode, null, null, false); + try (DebugContext debug = openDebugContext(DebugContext.forCurrentThread())) { + try (DebugContext.Scope d = debug.scope("CompilingStub", providers.getCodeCache(), debugScopeContext())) { + CodeCacheProvider codeCache = providers.getCodeCache(); + CompilationResult compResult = buildCompilationResult(debug, backend); + try (DebugContext.Scope s = debug.scope("CodeInstall", compResult); + DebugContext.Activation a = debug.activate()) { + assert destroyedCallerRegisters != null; + // Add a GeneratePIC check here later, we don't want to install + // code if we don't have a corresponding VM global symbol. + HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult); + code = codeCache.installCode(null, compiledCode, null, null, false); + } catch (Throwable e) { + throw debug.handle(e); + } } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } - } catch (Throwable e) { - throw Debug.handle(e); + assert code != null : "error installing stub " + this; } - assert code != null : "error installing stub " + this; } return code; } @SuppressWarnings("try") - private CompilationResult buildCompilationResult(final Backend backend) { - CompilationResult compResult = new CompilationResult(toString(), GeneratePIC.getValue()); - final StructuredGraph graph = getGraph(getStubCompilationId()); + private CompilationResult buildCompilationResult(DebugContext debug, final Backend backend) { + CompilationResult compResult = new CompilationResult(toString(), GeneratePIC.getValue(options)); + final StructuredGraph graph = getGraph(debug, getStubCompilationId()); // Stubs cannot be recompiled so they cannot be compiled with assumptions assert graph.getAssumptions() == null; @@ -211,14 +228,14 @@ public abstract class Stub { graph.replaceFixed(graph.start(), newStart); } - try (Scope s0 = Debug.scope("StubCompilation", graph, providers.getCodeCache())) { + try (DebugContext.Scope s0 = debug.scope("StubCompilation", graph, providers.getCodeCache())) { Suites suites = createSuites(); emitFrontEnd(providers, backend, graph, providers.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, DefaultProfilingInfo.get(TriState.UNKNOWN), suites); LIRSuites lirSuites = createLIRSuites(); emitBackEnd(graph, Stub.this, getInstalledCodeOwner(), backend, compResult, CompilationResultBuilderFactory.Default, getRegisterConfig(), lirSuites); assert checkStubInvariants(compResult); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } return compResult; } @@ -227,11 +244,11 @@ public abstract class Stub { * Gets a {@link CompilationResult} that can be used for code generation. Required for AOT. */ @SuppressWarnings("try") - public CompilationResult getCompilationResult(final Backend backend) { - try (Scope d = Debug.sandbox("CompilingStub", DebugScope.getConfig(), providers.getCodeCache(), debugScopeContext())) { - return buildCompilationResult(backend); + public CompilationResult getCompilationResult(DebugContext debug, final Backend backend) { + try (DebugContext.Scope d = debug.scope("CompilingStub", providers.getCodeCache(), debugScopeContext())) { + return buildCompilationResult(debug, backend); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } } @@ -275,12 +292,12 @@ public abstract class Stub { } protected Suites createSuites() { - Suites defaultSuites = providers.getSuites().getDefaultSuites(); + Suites defaultSuites = providers.getSuites().getDefaultSuites(options); return new Suites(new PhaseSuite<>(), defaultSuites.getMidTier(), defaultSuites.getLowTier()); } protected LIRSuites createLIRSuites() { - LIRSuites lirSuites = new LIRSuites(providers.getSuites().getDefaultLIRSuites()); + LIRSuites lirSuites = new LIRSuites(providers.getSuites().getDefaultLIRSuites(options)); ListIterator> moveProfiling = lirSuites.getPostAllocationOptimizationStage().findPhase(MoveProfilingPhase.class); if (moveProfiling != null) { moveProfiling.remove(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubOptions.java index 87425f72781..c4db6e94c01 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubOptions.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.hotspot.stubs; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; +import org.graalvm.compiler.options.OptionKey; //JaCoCo Exclude @@ -37,18 +37,18 @@ import org.graalvm.compiler.options.OptionValue; public class StubOptions { // @formatter:off @Option(help = "Trace execution of stub used to handle an exception thrown by a callee.", type = OptionType.Debug) - static final OptionValue TraceExceptionHandlerStub = new OptionValue<>(false); + static final OptionKey TraceExceptionHandlerStub = new OptionKey<>(false); @Option(help = "Trace execution of the stub that routes an exception to a handler in the calling frame.", type = OptionType.Debug) - static final OptionValue TraceUnwindStub = new OptionValue<>(false); + static final OptionKey TraceUnwindStub = new OptionKey<>(false); @Option(help = "Trace execution of slow path stub for array allocation.", type = OptionType.Debug) - static final OptionValue TraceNewArrayStub = new OptionValue<>(false); + static final OptionKey TraceNewArrayStub = new OptionKey<>(false); @Option(help = "Trace execution of slow path stub for non-array object allocation.", type = OptionType.Debug) - static final OptionValue TraceNewInstanceStub = new OptionValue<>(false); + static final OptionKey TraceNewInstanceStub = new OptionKey<>(false); @Option(help = "Force non-array object allocation to always use the slow path.", type = OptionType.Debug) - static final OptionValue ForceUseOfNewInstanceStub = new OptionValue<>(false); + static final OptionKey ForceUseOfNewInstanceStub = new OptionKey<>(false); //@formatter:on } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java index 169a03ede3f..725bb138bf5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java @@ -22,14 +22,13 @@ */ package org.graalvm.compiler.hotspot.stubs; +import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getAndClearObjectResult; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.loadHubIntrinsic; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOops; import static org.graalvm.compiler.replacements.nodes.CStringConstant.cstring; -import static org.graalvm.compiler.word.Word.unsigned; -import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -43,15 +42,16 @@ import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; import org.graalvm.compiler.hotspot.nodes.DeoptimizeCallerNode; -import org.graalvm.compiler.hotspot.nodes.SnippetAnchorNode; import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; import org.graalvm.compiler.hotspot.nodes.VMErrorNode; import org.graalvm.compiler.hotspot.word.KlassPointer; import org.graalvm.compiler.nodes.PiNode; +import org.graalvm.compiler.nodes.SnippetAnchorNode; import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.replacements.Log; -import org.graalvm.compiler.word.Pointer; import org.graalvm.compiler.word.Word; +import org.graalvm.word.Pointer; +import org.graalvm.word.WordFactory; import jdk.vm.ci.meta.DeoptimizationAction; @@ -171,7 +171,7 @@ public class StubUtil { * Analyzes a given value and prints information about it to the log stream. */ public static void decipher(long value) { - vmMessageC(VM_MESSAGE_C, false, Word.zero(), value, 0L, 0L); + vmMessageC(VM_MESSAGE_C, false, WordFactory.zero(), value, 0L, 0L); } /** @@ -233,14 +233,14 @@ public class StubUtil { */ public static Object verifyObject(Object object) { if (verifyOops(INJECTED_VMCONFIG)) { - Word verifyOopCounter = Word.unsigned(verifyOopCounterAddress(INJECTED_VMCONFIG)); + Word verifyOopCounter = WordFactory.unsigned(verifyOopCounterAddress(INJECTED_VMCONFIG)); verifyOopCounter.writeInt(0, verifyOopCounter.readInt(0) + 1); Pointer oop = Word.objectToTrackedPointer(object); if (object != null) { GuardingNode anchorNode = SnippetAnchorNode.anchor(); // make sure object is 'reasonable' - if (!oop.and(unsigned(verifyOopMask(INJECTED_VMCONFIG))).equal(unsigned(verifyOopBits(INJECTED_VMCONFIG)))) { + if (!oop.and(WordFactory.unsigned(verifyOopMask(INJECTED_VMCONFIG))).equal(WordFactory.unsigned(verifyOopBits(INJECTED_VMCONFIG)))) { fatal("oop not in heap: %p", oop.rawValue()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UncommonTrapStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UncommonTrapStub.java deleted file mode 100644 index 2c981eaee79..00000000000 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UncommonTrapStub.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.graalvm.compiler.hotspot.stubs; - -import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; -import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.PreferGraalStubs; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readPendingDeoptimization; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writePendingDeoptimization; -import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.writeRegisterAsWord; - -import org.graalvm.compiler.api.replacements.Fold; -import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; -import org.graalvm.compiler.api.replacements.Snippet; -import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; -import org.graalvm.compiler.debug.GraalError; -import org.graalvm.compiler.graph.Node.ConstantNodeParameter; -import org.graalvm.compiler.graph.Node.NodeIntrinsic; -import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; -import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; -import org.graalvm.compiler.hotspot.meta.HotSpotProviders; -import org.graalvm.compiler.hotspot.nodes.SaveAllRegistersNode; -import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; -import org.graalvm.compiler.hotspot.nodes.UncommonTrapCallNode; -import org.graalvm.compiler.nodes.NamedLocationIdentity; -import org.graalvm.compiler.word.Word; - -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.TargetDescription; - -/** - * Uncommon trap stub. - * - * This is the entry point for code which is returning to a de-optimized frame. - * - * The steps taken by this frame are as follows: - * - *

    20. push a dummy "register_save" and save the return values (O0, O1, F0/F1, G1) and all - * potentially live registers (at a pollpoint many registers can be live). - * - *
    21. call the C routine: Deoptimization::fetch_unroll_info (this function returns information - * about the number and size of interpreter frames which are equivalent to the frame which is being - * deoptimized) - * - *
    22. deallocate the unpack frame, restoring only results values. Other volatile registers will now - * be captured in the vframeArray as needed. - * - *
    23. deallocate the deoptimization frame - * - *
    24. in a loop using the information returned in the previous step push new interpreter frames - * (take care to propagate the return values through each new frame pushed) - * - *
    25. create a dummy "unpack_frame" and save the return values (O0, O1, F0) - * - *
    26. call the C routine: Deoptimization::unpack_frames (this function lays out values on the - * interpreter frame which was just created) - * - *
    27. deallocate the dummy unpack_frame - * - *
    28. ensure that all the return values are correctly set and then do a return to the interpreter - * entry point - * - *

      - * ATTENTION: We cannot do any complicated operations e.g. logging via printf in this snippet - * because we change the current stack layout and so the code is very sensitive to register - * allocation. - */ -public class UncommonTrapStub extends SnippetStub { - - public static final LocationIdentity STACK_BANG_LOCATION = NamedLocationIdentity.mutable("stack bang"); - - private final TargetDescription target; - - public UncommonTrapStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { - super(UncommonTrapStub.class, "uncommonTrapHandler", providers, linkage); - this.target = target; - assert PreferGraalStubs.getValue(); - } - - @Override - public boolean preservesRegisters() { - return false; - } - - @Override - protected Object getConstantParameterValue(int index, String name) { - switch (index) { - case 0: - return providers.getRegisters().getThreadRegister(); - case 1: - return providers.getRegisters().getStackPointerRegister(); - default: - throw GraalError.shouldNotReachHere("unknown parameter " + name + " at index " + index); - } - } - - /** - * Uncommon trap handler. - * - * We save the argument return registers. We call the first C routine, fetch_unroll_info(). This - * routine captures the return values and returns a structure which describes the current frame - * size and the sizes of all replacement frames. The current frame is compiled code and may - * contain many inlined functions, each with their own JVM state. We pop the current frame, then - * push all the new frames. Then we call the C routine unpack_frames() to populate these frames. - * Finally unpack_frames() returns us the new target address. Notice that callee-save registers - * are BLOWN here; they have already been captured in the vframeArray at the time the return PC - * was patched. - */ - @Snippet - private static void uncommonTrapHandler(@ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister) { - final Word thread = registerAsWord(threadRegister); - final long registerSaver = SaveAllRegistersNode.saveAllRegisters(); - - final int actionAndReason = readPendingDeoptimization(thread); - writePendingDeoptimization(thread, -1); - - final Word unrollBlock = UncommonTrapCallNode.uncommonTrap(registerSaver, actionAndReason, deoptimizationUnpackUncommonTrap(INJECTED_VMCONFIG)); - - DeoptimizationStub.deoptimizationCommon(stackPointerRegister, thread, registerSaver, unrollBlock); - } - - /** - * Reads the value of the passed register as a Word. - */ - private static Word readRegister(Register register) { - return registerAsWord(register, false, false); - } - - /** - * Writes the value of the passed register. - * - * @param value value the register should be set to - */ - private static void writeRegister(Register register, Word value) { - writeRegisterAsWord(register, value); - } - - @Fold - static int stackShadowPages(@InjectedParameter GraalHotSpotVMConfig config) { - return config.useStackBanging ? config.stackShadowPages : 0; - } - - /** - * Returns the stack bias for the host architecture. - * - * @deprecated This method should go away as soon as JDK-8032410 hits the Graal repository. - * - * @return stack bias - */ - @Deprecated - @Fold - static int stackBias(@InjectedParameter GraalHotSpotVMConfig config) { - return config.stackBias; - } - - @Fold - static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; - } - - @Fold - static int deoptimizationUnrollBlockCallerAdjustmentOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockCallerAdjustmentOffset; - } - - @Fold - static int deoptimizationUnrollBlockNumberOfFramesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockNumberOfFramesOffset; - } - - @Fold - static int deoptimizationUnrollBlockTotalFrameSizesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockTotalFrameSizesOffset; - } - - @Fold - static int deoptimizationUnrollBlockFrameSizesOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockFrameSizesOffset; - } - - @Fold - static int deoptimizationUnrollBlockFramePcsOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockFramePcsOffset; - } - - @Fold - static int deoptimizationUnrollBlockInitialInfoOffset(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnrollBlockInitialInfoOffset; - } - - @Fold - static int deoptimizationUnpackDeopt(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnpackDeopt; - } - - @Fold - static int deoptimizationUnpackUncommonTrap(@InjectedParameter GraalHotSpotVMConfig config) { - return config.deoptimizationUnpackUncommonTrap; - } - - @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) - public static native int unpackFrames(@ConstantNodeParameter ForeignCallDescriptor unpackFrames, Word thread, int mode); -} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java index 5c8e0869c3d..a3c34070a2c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java @@ -22,6 +22,7 @@ */ package org.graalvm.compiler.hotspot.stubs; +import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; import static org.graalvm.compiler.hotspot.nodes.JumpToExceptionHandlerInCallerNode.jumpToExceptionHandlerInCaller; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; import static org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub.checkExceptionNotNull; @@ -36,6 +37,7 @@ import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter; import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; +import org.graalvm.compiler.debug.Assertions; import org.graalvm.compiler.graph.Node.ConstantNodeParameter; import org.graalvm.compiler.graph.Node.NodeIntrinsic; import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; @@ -43,8 +45,9 @@ import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode; import org.graalvm.compiler.nodes.UnwindNode; -import org.graalvm.compiler.word.Pointer; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.word.Word; +import org.graalvm.word.Pointer; import jdk.vm.ci.code.Register; @@ -54,8 +57,8 @@ import jdk.vm.ci.code.Register; */ public class UnwindExceptionToCallerStub extends SnippetStub { - public UnwindExceptionToCallerStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("unwindExceptionToCaller", providers, linkage); + public UnwindExceptionToCallerStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("unwindExceptionToCaller", options, providers, linkage); } /** @@ -69,14 +72,17 @@ public class UnwindExceptionToCallerStub extends SnippetStub { @Override protected Object getConstantParameterValue(int index, String name) { - assert index == 2; - return providers.getRegisters().getThreadRegister(); + if (index == 2) { + return providers.getRegisters().getThreadRegister(); + } + assert index == 3; + return options; } @Snippet - private static void unwindExceptionToCaller(Object exception, Word returnAddress, @ConstantParameter Register threadRegister) { + private static void unwindExceptionToCaller(Object exception, Word returnAddress, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) { Pointer exceptionOop = Word.objectToTrackedPointer(exception); - if (logging()) { + if (logging(options)) { printf("unwinding exception %p (", exceptionOop.rawValue()); decipher(exceptionOop.rawValue()); printf(") at %p (", returnAddress.rawValue()); @@ -84,12 +90,12 @@ public class UnwindExceptionToCallerStub extends SnippetStub { printf(")\n"); } Word thread = registerAsWord(threadRegister); - checkNoExceptionInThread(thread, assertionsEnabled(null)); - checkExceptionNotNull(assertionsEnabled(null), exception); + checkNoExceptionInThread(thread, assertionsEnabled(INJECTED_VMCONFIG)); + checkExceptionNotNull(assertionsEnabled(INJECTED_VMCONFIG), exception); Word handlerInCallerPc = exceptionHandlerForReturnAddress(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, thread, returnAddress); - if (logging()) { + if (logging(options)) { printf("handler for exception %p at return address %p is at %p (", exceptionOop.rawValue(), returnAddress.rawValue(), handlerInCallerPc.rawValue()); decipher(handlerInCallerPc.rawValue()); printf(")\n"); @@ -99,28 +105,23 @@ public class UnwindExceptionToCallerStub extends SnippetStub { } @Fold - static boolean logging() { - return StubOptions.TraceUnwindStub.getValue(); + static boolean logging(OptionValues options) { + return StubOptions.TraceUnwindStub.getValue(options); } /** - * Determines if either Java assertions are enabled for {@link UnwindExceptionToCallerStub} or - * if this is a HotSpot build where the ASSERT mechanism is enabled. - *

      - * This first check relies on the per-class assertion status which is why this method must be in - * this class. + * Determines if either Java assertions are enabled for Graal or if this is a HotSpot build + * where the ASSERT mechanism is enabled. */ @Fold @SuppressWarnings("all") static boolean assertionsEnabled(@InjectedParameter GraalHotSpotVMConfig config) { - boolean enabled = false; - assert enabled = true; - return enabled || cAssertionsEnabled(config); + return Assertions.assertionsEnabled() || cAssertionsEnabled(config); } public static final ForeignCallDescriptor EXCEPTION_HANDLER_FOR_RETURN_ADDRESS = newDescriptor(UnwindExceptionToCallerStub.class, "exceptionHandlerForReturnAddress", Word.class, Word.class, Word.class); - @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) + @NodeIntrinsic(value = StubForeignCallNode.class) public static native Word exceptionHandlerForReturnAddress(@ConstantNodeParameter ForeignCallDescriptor exceptionHandlerForReturnAddress, Word thread, Word returnAddress); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/VerifyOopStub.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/VerifyOopStub.java index ea11ef50079..dcd7442d462 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/VerifyOopStub.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/VerifyOopStub.java @@ -28,14 +28,15 @@ import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage; import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import org.graalvm.compiler.hotspot.meta.HotSpotProviders; +import org.graalvm.compiler.options.OptionValues; /** * Stub called via {@link HotSpotHostForeignCallsProvider#VERIFY_OOP}. */ public class VerifyOopStub extends SnippetStub { - public VerifyOopStub(HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { - super("verifyOop", providers, linkage); + public VerifyOopStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) { + super("verifyOop", options, providers, linkage); } @Snippet diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/KlassPointer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/KlassPointer.java index 0cad4f425eb..7efa5fa81de 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/KlassPointer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/KlassPointer.java @@ -27,10 +27,10 @@ import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.P import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.READ_KLASS_POINTER; import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.TO_KLASS_POINTER; -import org.graalvm.compiler.core.common.LocationIdentity; -import org.graalvm.compiler.word.Pointer; import org.graalvm.compiler.word.Word.Opcode; import org.graalvm.compiler.word.Word.Operation; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.Pointer; /** * Marker type for a metaspace pointer to a type. diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java index 434471c08b7..22a64302a89 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java @@ -25,15 +25,15 @@ package org.graalvm.compiler.hotspot.word; import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.FROM_POINTER; import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.IS_NULL; -import org.graalvm.compiler.core.common.LocationIdentity; import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; -import org.graalvm.compiler.word.Pointer; -import org.graalvm.compiler.word.Signed; -import org.graalvm.compiler.word.Unsigned; import org.graalvm.compiler.word.Word; import org.graalvm.compiler.word.Word.Opcode; import org.graalvm.compiler.word.Word.Operation; -import org.graalvm.compiler.word.WordBase; +import org.graalvm.word.LocationIdentity; +import org.graalvm.word.Pointer; +import org.graalvm.word.SignedWord; +import org.graalvm.word.UnsignedWord; +import org.graalvm.word.WordBase; /** * Marker type for a metaspace pointer. @@ -50,8 +50,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -65,8 +65,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -80,8 +80,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -95,8 +95,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -110,8 +110,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -125,8 +125,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -140,8 +140,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -155,8 +155,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -170,8 +170,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -284,8 +284,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -299,8 +299,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -314,8 +314,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -329,8 +329,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -344,8 +344,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -359,8 +359,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -374,8 +374,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -389,8 +389,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -404,8 +404,8 @@ public abstract class MetaspacePointer { * Initializes the memory at address {@code (this + offset)}. Both the base address and offset * are in bytes. The memory must be uninitialized or zero prior to this operation. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -419,8 +419,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -518,17 +518,6 @@ public abstract class MetaspacePointer { @Operation(opcode = Opcode.WRITE_POINTER) public abstract void writeWord(int offset, WordBase val, LocationIdentity locationIdentity); - /** - * Initializes the memory at address {@code (this + offset)}. Both the base address and offset - * are in bytes. The memory must be uninitialized or zero prior to this operation. - * - * @param offset the signed offset for the memory access - * @param locationIdentity the identity of the write - * @param val the value to be written to memory - */ - @Operation(opcode = Opcode.INITIALIZE) - public abstract void initializeLong(int offset, long val, LocationIdentity locationIdentity); - /** * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. @@ -544,8 +533,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -558,8 +547,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -572,8 +561,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -586,8 +575,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -600,8 +589,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -614,8 +603,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -628,8 +617,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -642,8 +631,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -656,8 +645,8 @@ public abstract class MetaspacePointer { * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -671,8 +660,8 @@ public abstract class MetaspacePointer { * the VM uses compressed oops, and it can be parameterized to allow read barriers (G1 referent * field). *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -788,8 +777,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -802,8 +791,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -816,8 +805,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -830,8 +819,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -844,8 +833,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -858,8 +847,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -872,8 +861,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -886,8 +875,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access @@ -900,8 +889,8 @@ public abstract class MetaspacePointer { * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in * bytes. *

      - * The offset is always treated as a {@link Signed} value. However, the static type is - * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller + * The offset is always treated as a {@link SignedWord} value. However, the static type is + * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller * knows that the highest-order bit of the unsigned value is never used). * * @param offset the signed offset for the memory access diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MethodPointer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MethodPointer.java index f00d0da5095..be27d05d013 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MethodPointer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MethodPointer.java @@ -26,7 +26,7 @@ import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.P import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.POINTER_NE; import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.TO_METHOD_POINTER; -import org.graalvm.compiler.word.Pointer; +import org.graalvm.word.Pointer; /** * Marker type for a metaspace pointer to a method. diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java index 725e6494bd5..39539b36238 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java @@ -81,7 +81,6 @@ import static org.graalvm.compiler.core.common.GraalOptions.SupportJsrBytecodes; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -93,9 +92,11 @@ import org.graalvm.compiler.bytecode.BytecodeStream; import org.graalvm.compiler.bytecode.BytecodeSwitch; import org.graalvm.compiler.bytecode.BytecodeTableSwitch; import org.graalvm.compiler.bytecode.Bytecodes; -import org.graalvm.compiler.common.PermanentBailoutException; -import org.graalvm.compiler.core.common.CollectionsFactory; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.core.common.PermanentBailoutException; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.meta.ExceptionHandler; @@ -157,7 +158,7 @@ public final class BciBlockMapping { public JSRData jsrData; public static class JSRData implements Cloneable { - public HashMap jsrAlternatives; + public EconomicMap jsrAlternatives; public JsrScope jsrScope = JsrScope.EMPTY_SCOPE; public BciBlock jsrSuccessor; public int jsrReturnBci; @@ -361,7 +362,7 @@ public final class BciBlockMapping { } } - public HashMap getJsrAlternatives() { + public EconomicMap getJsrAlternatives() { if (this.jsrData == null) { return null; } else { @@ -372,7 +373,7 @@ public final class BciBlockMapping { public void initJsrAlternatives() { JSRData data = this.getOrCreateJSRData(); if (data.jsrAlternatives == null) { - data.jsrAlternatives = new HashMap<>(); + data.jsrAlternatives = EconomicMap.create(Equivalence.DEFAULT); } } @@ -415,7 +416,7 @@ public final class BciBlockMapping { public static class ExceptionDispatchBlock extends BciBlock { - private HashMap exceptionDispatch = new HashMap<>(); + private EconomicMap exceptionDispatch = EconomicMap.create(Equivalence.DEFAULT); public ExceptionHandler handler; public int deoptBci; @@ -436,14 +437,14 @@ public final class BciBlockMapping { private static final int LOOP_HEADER_INITIAL_CAPACITY = 4; private int blocksNotYetAssignedId; - public int returnCount; - private int returnBci; + private final DebugContext debug; /** * Creates a new BlockMap instance from {@code code}. */ - private BciBlockMapping(Bytecode code) { + private BciBlockMapping(Bytecode code, DebugContext debug) { this.code = code; + this.debug = debug; this.exceptionHandlers = code.getExceptionHandlers(); } @@ -451,25 +452,21 @@ public final class BciBlockMapping { return this.blocks; } - public int getReturnCount() { - return this.returnCount; - } - /** * Builds the block map and conservative CFG and numbers blocks. */ - public void build(BytecodeStream stream) { + public void build(BytecodeStream stream, OptionValues options) { int codeSize = code.getCodeSize(); BciBlock[] blockMap = new BciBlock[codeSize]; makeExceptionEntries(blockMap); iterateOverBytecodes(blockMap, stream); if (hasJsrBytecodes) { - if (!SupportJsrBytecodes.getValue()) { + if (!SupportJsrBytecodes.getValue(options)) { throw new JsrNotSupportedBailout("jsr/ret parsing disabled"); } createJsrAlternatives(blockMap, blockMap[0]); } - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { this.log(blockMap, "Before BlockOrder"); } computeBlockOrder(blockMap); @@ -478,7 +475,7 @@ public final class BciBlockMapping { assert verify(); startBlock = blockMap[0]; - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { this.log(blockMap, "Before LivenessAnalysis"); } } @@ -532,9 +529,7 @@ public final class BciBlockMapping { case DRETURN: // fall through case ARETURN: // fall through case RETURN: { - returnCount++; current = null; - returnBci = bci; break; } case ATHROW: { @@ -710,7 +705,7 @@ public final class BciBlockMapping { block.addSuccessor(block.getRetSuccessor()); assert block.getRetSuccessor() != block.getJsrSuccessor(); } - Debug.log("JSR alternatives block %s sux %s jsrSux %s retSux %s jsrScope %s", block, block.getSuccessors(), block.getJsrSuccessor(), block.getRetSuccessor(), block.getJsrScope()); + debug.log("JSR alternatives block %s sux %s jsrSux %s retSux %s jsrScope %s", block, block.getSuccessors(), block.getJsrSuccessor(), block.getRetSuccessor(), block.getJsrScope()); if (block.getJsrSuccessor() != null || !scope.isEmpty()) { for (int i = 0; i < block.getSuccessorCount(); i++) { @@ -753,7 +748,14 @@ public final class BciBlockMapping { } } - private HashMap initialExceptionDispatch = CollectionsFactory.newMap(); + private EconomicMap initialExceptionDispatch; + + private EconomicMap getInitialExceptionDispatch() { + if (initialExceptionDispatch == null) { + initialExceptionDispatch = EconomicMap.create(Equivalence.DEFAULT); + } + return initialExceptionDispatch; + } private ExceptionDispatchBlock handleExceptions(BciBlock[] blockMap, int bci) { ExceptionDispatchBlock lastHandler = null; @@ -767,7 +769,7 @@ public final class BciBlockMapping { lastHandler = null; } - HashMap exceptionDispatch = lastHandler != null ? lastHandler.exceptionDispatch : initialExceptionDispatch; + EconomicMap exceptionDispatch = lastHandler != null ? lastHandler.exceptionDispatch : getInitialExceptionDispatch(); ExceptionDispatchBlock curHandler = exceptionDispatch.get(h); if (curHandler == null) { curHandler = new ExceptionDispatchBlock(); @@ -824,7 +826,7 @@ public final class BciBlockMapping { // Purge null entries for unreached blocks and sort blocks such that loop bodies are always // consecutively in the array. - int blockCount = maxBlocks - blocksNotYetAssignedId + 2; + int blockCount = maxBlocks - blocksNotYetAssignedId + 1; BciBlock[] newBlocks = new BciBlock[blockCount]; int next = 0; for (int i = 0; i < blocks.length; ++i) { @@ -837,13 +839,7 @@ public final class BciBlockMapping { } } } - - // Add return block. - BciBlock returnBlock = new BciBlock(); - returnBlock.startBci = returnBci; - returnBlock.endBci = returnBci; - returnBlock.setId(newBlocks.length - 2); - newBlocks[newBlocks.length - 2] = returnBlock; + assert next == newBlocks.length - 1; // Add unwind block. ExceptionDispatchBlock unwindBlock = new ExceptionDispatchBlock(); @@ -876,9 +872,9 @@ public final class BciBlockMapping { } public void log(BciBlock[] blockMap, String name) { - if (Debug.isLogEnabled()) { + if (debug.isLogEnabled()) { String n = System.lineSeparator(); - StringBuilder sb = new StringBuilder(Debug.currentScope()).append("BlockMap ").append(name).append(" :"); + StringBuilder sb = new StringBuilder(debug.getCurrentScopeName()).append("BlockMap ").append(name).append(" :"); sb.append(n); Iterable it; if (blocks == null) { @@ -911,7 +907,7 @@ public final class BciBlockMapping { } sb.append(n); } - Debug.log("%s", sb); + debug.log("%s", sb); } } @@ -952,7 +948,7 @@ public final class BciBlockMapping { assert block.loops == 0; block.loops = 1L << nextLoop; - Debug.log("makeLoopHeader(%s) -> %x", block, block.loops); + debug.log("makeLoopHeader(%s) -> %x", block, block.loops); if (loopHeaders == null) { loopHeaders = new BciBlock[LOOP_HEADER_INITIAL_CAPACITY]; } else if (nextLoop >= loopHeaders.length) { @@ -998,7 +994,7 @@ public final class BciBlockMapping { } block.loops = loops; - Debug.log("computeBlockOrder(%s) -> %x", block, block.loops); + debug.log("computeBlockOrder(%s) -> %x", block, block.loops); if (block.isLoopHeader) { loops &= ~(1L << block.loopId); @@ -1030,7 +1026,7 @@ public final class BciBlockMapping { if (block.loops != loops) { loopChanges = true; block.loops = loops; - Debug.log("fixLoopBits0(%s) -> %x", block, block.loops); + debug.log("fixLoopBits0(%s) -> %x", block, block.loops); } if (block.isLoopHeader) { @@ -1040,11 +1036,11 @@ public final class BciBlockMapping { return loops; } - public static BciBlockMapping create(BytecodeStream stream, Bytecode code) { - BciBlockMapping map = new BciBlockMapping(code); - map.build(stream); - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL)) { - Debug.dump(Debug.INFO_LOG_LEVEL, map, code.getMethod().format("After block building %f %R %H.%n(%P)")); + public static BciBlockMapping create(BytecodeStream stream, Bytecode code, OptionValues options, DebugContext debug) { + BciBlockMapping map = new BciBlockMapping(code, debug); + map.build(stream, options); + if (debug.isDumpEnabled(DebugContext.INFO_LEVEL)) { + debug.dump(DebugContext.INFO_LEVEL, map, code.getMethod().format("After block building %f %R %H.%n(%P)")); } return map; @@ -1058,10 +1054,6 @@ public final class BciBlockMapping { return startBlock; } - public BciBlock getReturnBlock() { - return blocks[blocks.length - 2]; - } - public ExceptionDispatchBlock getUnwindBlock() { return (ExceptionDispatchBlock) blocks[blocks.length - 1]; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java index 7ace642641e..6160540dd56 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java @@ -22,6 +22,20 @@ */ package org.graalvm.compiler.java; +import static java.lang.String.format; +import static java.lang.reflect.Modifier.STATIC; +import static java.lang.reflect.Modifier.SYNCHRONIZED; +import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; +import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; +import static jdk.vm.ci.meta.DeoptimizationAction.None; +import static jdk.vm.ci.meta.DeoptimizationReason.ClassCastException; +import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch; +import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException; +import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; +import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated; +import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode; +import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved; +import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI; import static org.graalvm.compiler.bytecode.Bytecodes.AALOAD; import static org.graalvm.compiler.bytecode.Bytecodes.AASTORE; import static org.graalvm.compiler.bytecode.Bytecodes.ACONST_NULL; @@ -227,39 +241,31 @@ import static org.graalvm.compiler.bytecode.Bytecodes.TABLESWITCH; import static org.graalvm.compiler.bytecode.Bytecodes.nameOf; import static org.graalvm.compiler.core.common.GraalOptions.DeoptALot; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining; import static org.graalvm.compiler.core.common.GraalOptions.PrintProfilingInformation; import static org.graalvm.compiler.core.common.GraalOptions.ResolveClassBeforeStaticInvoke; +import static org.graalvm.compiler.core.common.GraalOptions.StressExplicitExceptionCode; import static org.graalvm.compiler.core.common.GraalOptions.StressInvokeWithExceptionNode; -import static org.graalvm.compiler.core.common.GraalOptions.UseGraalInstrumentation; import static org.graalvm.compiler.core.common.type.StampFactory.objectNonNull; import static org.graalvm.compiler.debug.GraalError.guarantee; import static org.graalvm.compiler.debug.GraalError.shouldNotReachHere; -import static org.graalvm.compiler.java.BytecodeParserOptions.DumpDuringGraphBuilding; +import static org.graalvm.compiler.java.BytecodeParserOptions.InlinePartialIntrinsicExitDuringParsing; +import static org.graalvm.compiler.java.BytecodeParserOptions.TraceBytecodeParserLevel; import static org.graalvm.compiler.java.BytecodeParserOptions.TraceInlineDuringParsing; import static org.graalvm.compiler.java.BytecodeParserOptions.TraceParserPlugins; import static org.graalvm.compiler.java.BytecodeParserOptions.UseGuardedIntrinsics; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY; +import static org.graalvm.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_DURING_PARSING; import static org.graalvm.compiler.nodes.type.StampTool.isPointerNonNull; -import static java.lang.String.format; -import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile; -import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile; -import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch; -import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException; -import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; -import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated; -import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode; -import static jdk.vm.ci.meta.DeoptimizationReason.Unresolved; -import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI; -import java.lang.ref.Reference; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Formatter; -import java.util.HashMap; import java.util.List; -import java.util.Map; +import org.graalvm.compiler.api.replacements.Snippet; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.BytecodeDisassembler; import org.graalvm.compiler.bytecode.BytecodeLookupSwitch; @@ -268,25 +274,23 @@ import org.graalvm.compiler.bytecode.BytecodeStream; import org.graalvm.compiler.bytecode.BytecodeSwitch; import org.graalvm.compiler.bytecode.BytecodeTableSwitch; import org.graalvm.compiler.bytecode.Bytecodes; +import org.graalvm.compiler.bytecode.Bytes; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecodeProvider; -import org.graalvm.compiler.common.PermanentBailoutException; -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.common.LocationIdentity; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.calc.Condition; import org.graalvm.compiler.core.common.calc.FloatConvert; import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; -import org.graalvm.compiler.core.common.type.AbstractPointerStamp; import org.graalvm.compiler.core.common.type.ObjectStamp; import org.graalvm.compiler.core.common.type.Stamp; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; import org.graalvm.compiler.core.common.type.TypeReference; import org.graalvm.compiler.core.common.util.Util; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.Debug.Scope; +import org.graalvm.compiler.debug.Assertions; +import org.graalvm.compiler.debug.CounterKey; import org.graalvm.compiler.debug.DebugCloseable; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.debug.Indent; import org.graalvm.compiler.debug.TTY; @@ -296,7 +300,6 @@ import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.graph.iterators.NodeIterable; import org.graalvm.compiler.java.BciBlockMapping.BciBlock; import org.graalvm.compiler.java.BciBlockMapping.ExceptionDispatchBlock; -import org.graalvm.compiler.nodeinfo.InputType; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractMergeNode; import org.graalvm.compiler.nodes.BeginNode; @@ -361,16 +364,14 @@ import org.graalvm.compiler.nodes.calc.SubNode; import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode; import org.graalvm.compiler.nodes.calc.XorNode; import org.graalvm.compiler.nodes.calc.ZeroExtendNode; -import org.graalvm.compiler.nodes.debug.instrumentation.InstrumentationBeginNode; import org.graalvm.compiler.nodes.extended.AnchoringNode; import org.graalvm.compiler.nodes.extended.BranchProbabilityNode; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode; -import org.graalvm.compiler.nodes.extended.GuardedNode; -import org.graalvm.compiler.nodes.extended.GuardingNode; import org.graalvm.compiler.nodes.extended.IntegerSwitchNode; import org.graalvm.compiler.nodes.extended.LoadHubNode; import org.graalvm.compiler.nodes.extended.LoadMethodNode; import org.graalvm.compiler.nodes.extended.MembarNode; +import org.graalvm.compiler.nodes.extended.StateSplitProxyNode; import org.graalvm.compiler.nodes.extended.ValueAnchorNode; import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; @@ -402,7 +403,12 @@ import org.graalvm.compiler.nodes.java.StoreIndexedNode; import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.nodes.type.StampTool; import org.graalvm.compiler.nodes.util.GraphUtil; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; +import org.graalvm.compiler.phases.util.ValueMergeUtil; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; +import org.graalvm.word.LocationIdentity; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.code.BytecodeFrame; @@ -426,6 +432,7 @@ import jdk.vm.ci.meta.RawConstant; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; import jdk.vm.ci.meta.TriState; /** @@ -448,9 +455,9 @@ public class BytecodeParser implements GraphBuilderContext { /** * Meters the number of actual bytecodes parsed. */ - public static final DebugCounter BytecodesParsed = Debug.counter("BytecodesParsed"); + public static final CounterKey BytecodesParsed = DebugContext.counter("BytecodesParsed"); - protected static final DebugCounter EXPLICIT_EXCEPTIONS = Debug.counter("ExplicitExceptions"); + protected static final CounterKey EXPLICIT_EXCEPTIONS = DebugContext.counter("ExplicitExceptions"); /** * A scoped object for tasks to be performed after parsing an intrinsic such as processing @@ -460,6 +467,7 @@ public class BytecodeParser implements GraphBuilderContext { FrameState stateBefore; final Mark mark; final BytecodeParser parser; + List returnDataList; /** * Creates a scope for root parsing an intrinsic. @@ -501,46 +509,53 @@ public class BytecodeParser implements GraphBuilderContext { * added to the graph while parsing/inlining the intrinsic for which this object exists. */ private void processPlaceholderFrameStates(IntrinsicContext intrinsic) { - FrameState stateAfterReturn = null; StructuredGraph graph = parser.getGraph(); + graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "Before processPlaceholderFrameStates in %s", parser.method); + boolean sawInvalidFrameState = false; for (Node node : graph.getNewNodes(mark)) { if (node instanceof FrameState) { FrameState frameState = (FrameState) node; if (BytecodeFrame.isPlaceholderBci(frameState.bci)) { if (frameState.bci == BytecodeFrame.AFTER_BCI) { - FrameStateBuilder frameStateBuilder = parser.frameState; - if (frameState.stackSize() != 0) { - assert frameState.usages().count() == 1; - ValueNode returnVal = frameState.stackAt(0); - assert returnVal == frameState.usages().first(); + if (parser.getInvokeReturnType() == null) { + // A frame state in a root compiled intrinsic. + assert intrinsic.isCompilationRoot(); + FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); + frameState.replaceAndDelete(newFrameState); + } else { + JavaKind returnKind = parser.getInvokeReturnType().getJavaKind(); + FrameStateBuilder frameStateBuilder = parser.frameState; + assert !frameState.rethrowException(); + if (frameState.stackSize() != 0) { + ValueNode returnVal = frameState.stackAt(0); + if (!ReturnToCallerData.containsReturnValue(returnDataList, returnVal)) { + throw new GraalError("AFTER_BCI frame state within an intrinsic has a non-return value on the stack: %s", returnVal); + } - if (parser.currentInvokeReturnType == null) { - assert intrinsic.isCompilationRoot(); - FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); - frameState.replaceAndDelete(newFrameState); - } else { - /* - * Swap the top-of-stack value with the side-effect return value - * using the frame state. - */ - JavaKind returnKind = parser.currentInvokeReturnType.getJavaKind(); + // Swap the top-of-stack value with the return value ValueNode tos = frameStateBuilder.pop(returnKind); assert tos.getStackKind() == returnVal.getStackKind(); FrameState newFrameState = frameStateBuilder.create(parser.stream.nextBCI(), parser.getNonIntrinsicAncestor(), false, new JavaKind[]{returnKind}, new ValueNode[]{returnVal}); frameState.replaceAndDelete(newFrameState); + newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition()); frameStateBuilder.push(returnKind, tos); + } else if (returnKind != JavaKind.Void) { + // If the intrinsic returns a non-void value, then any frame + // state with an empty stack is invalid as it cannot + // be used to deoptimize to just after the call returns. + // These invalid frame states are expected to be removed + // by later compilation stages. + FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); + newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition()); + frameState.replaceAndDelete(newFrameState); + sawInvalidFrameState = true; + } else { + // An intrinsic for a void method. + FrameState newFrameState = frameStateBuilder.create(parser.stream.nextBCI(), null); + newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition()); + frameState.replaceAndDelete(newFrameState); } - } else { - if (stateAfterReturn == null) { - if (intrinsic != null) { - assert intrinsic.isCompilationRoot(); - stateAfterReturn = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI)); - } else { - stateAfterReturn = frameStateBuilder.create(parser.stream.nextBCI(), null); - } - } - frameState.replaceAndDelete(stateAfterReturn); } } else if (frameState.bci == BytecodeFrame.BEFORE_BCI) { if (stateBefore == null) { @@ -549,12 +564,41 @@ public class BytecodeParser implements GraphBuilderContext { if (stateBefore != frameState) { frameState.replaceAndDelete(stateBefore); } + } else if (frameState.bci == BytecodeFrame.AFTER_EXCEPTION_BCI) { + // This is a frame state for the entry point to an exception + // dispatcher in an intrinsic. For example, the invoke denoting + // a partial intrinsic exit will have an edge to such a + // dispatcher if the profile for the original invoke being + // intrinsified indicates an exception was seen. As per JVM + // bytecode semantics, the interpreter expects a single + // value on the stack on entry to an exception handler, + // namely the exception object. + assert frameState.rethrowException(); + ExceptionObjectNode exceptionObject = (ExceptionObjectNode) frameState.stackAt(0); + FrameStateBuilder dispatchState = parser.frameState.copy(); + dispatchState.clearStack(); + dispatchState.push(JavaKind.Object, exceptionObject); + dispatchState.setRethrowException(true); + FrameState newFrameState = dispatchState.create(parser.bci(), exceptionObject); + frameState.replaceAndDelete(newFrameState); + newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition()); } else { assert frameState.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI; } } } } + if (sawInvalidFrameState) { + JavaKind returnKind = parser.getInvokeReturnType().getJavaKind(); + FrameStateBuilder frameStateBuilder = parser.frameState; + ValueNode returnValue = frameStateBuilder.pop(returnKind); + StateSplitProxyNode proxy = graph.add(new StateSplitProxyNode(returnValue)); + parser.lastInstr.setNext(proxy); + frameStateBuilder.push(returnKind, proxy); + proxy.setStateAfter(parser.createFrameState(parser.stream.nextBCI(), proxy)); + parser.lastInstr = proxy; + } + graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "After processPlaceholderFrameStates in %s", parser.method); } } @@ -580,8 +624,29 @@ public class BytecodeParser implements GraphBuilderContext { } } + protected static class ReturnToCallerData { + protected final ValueNode returnValue; + protected final FixedWithNextNode beforeReturnNode; + + protected ReturnToCallerData(ValueNode returnValue, FixedWithNextNode beforeReturnNode) { + this.returnValue = returnValue; + this.beforeReturnNode = beforeReturnNode; + } + + static boolean containsReturnValue(List list, ValueNode value) { + for (ReturnToCallerData e : list) { + if (e.returnValue == value) { + return true; + } + } + return false; + } + } + private final GraphBuilderPhase.Instance graphBuilderInstance; protected final StructuredGraph graph; + protected final OptionValues options; + protected final DebugContext debug; private BciBlockMapping blockMap; private LocalLiveness liveness; @@ -594,8 +659,7 @@ public class BytecodeParser implements GraphBuilderContext { private ValueNode methodSynchronizedObject; - private ValueNode returnValue; - private FixedWithNextNode beforeReturnNode; + private List returnDataList; private ValueNode unwindValue; private FixedWithNextNode beforeUnwindNode; @@ -606,8 +670,6 @@ public class BytecodeParser implements GraphBuilderContext { private FixedWithNextNode[] firstInstructionArray; private FrameStateBuilder[] entryStateArray; - private int lastBCI; // BCI of lastInstr. This field is for resolving instrumentation target. - private boolean finalBarrierRequired; private ValueNode originalReceiver; @@ -618,6 +680,8 @@ public class BytecodeParser implements GraphBuilderContext { this.method = code.getMethod(); this.graphBuilderInstance = graphBuilderInstance; this.graph = graph; + this.options = graph.getOptions(); + this.debug = graph.getDebug(); this.graphBuilderConfig = graphBuilderInstance.graphBuilderConfig; this.optimisticOpts = graphBuilderInstance.optimisticOpts; this.metaAccess = graphBuilderInstance.metaAccess; @@ -630,7 +694,6 @@ public class BytecodeParser implements GraphBuilderContext { this.intrinsicContext = intrinsicContext; this.entryBCI = entryBCI; this.parent = parent; - this.lastBCI = -1; assert code.getCode() != null : "method must contain bytecodes: " + method; @@ -644,14 +707,6 @@ public class BytecodeParser implements GraphBuilderContext { return graphBuilderInstance; } - public ValueNode getReturnValue() { - return returnValue; - } - - public FixedWithNextNode getBeforeReturnNode() { - return this.beforeReturnNode; - } - public ValueNode getUnwindValue() { return unwindValue; } @@ -675,12 +730,12 @@ public class BytecodeParser implements GraphBuilderContext { @SuppressWarnings("try") protected void build(FixedWithNextNode startInstruction, FrameStateBuilder startFrameState) { - if (PrintProfilingInformation.getValue() && profilingInfo != null) { + if (PrintProfilingInformation.getValue(options) && profilingInfo != null) { TTY.println("Profiling info for " + method.format("%H.%n(%p)")); TTY.println(Util.indent(profilingInfo.toString(method, CodeUtil.NEW_LINE), " ")); } - try (Indent indent = Debug.logAndIndent("build graph for %s", method)) { + try (Indent indent = debug.logAndIndent("build graph for %s", method)) { if (bytecodeProvider.shouldRecordMethodDependencies()) { assert getParent() != null || method.equals(graph.method()); // Record method dependency in the graph @@ -688,7 +743,7 @@ public class BytecodeParser implements GraphBuilderContext { } // compute the block map, setup exception handlers and get the entrypoint(s) - BciBlockMapping newMapping = BciBlockMapping.create(stream, code); + BciBlockMapping newMapping = BciBlockMapping.create(stream, code, options, graph.getDebug()); this.blockMap = newMapping; this.firstInstructionArray = new FixedWithNextNode[blockMap.getBlockCount()]; this.entryStateArray = new FrameStateBuilder[blockMap.getBlockCount()]; @@ -702,11 +757,11 @@ public class BytecodeParser implements GraphBuilderContext { */ assert computeKindVerification(startFrameState); - try (Scope s = Debug.scope("LivenessAnalysis")) { + try (DebugContext.Scope s = debug.scope("LivenessAnalysis")) { int maxLocals = method.getMaxLocals(); - liveness = LocalLiveness.compute(stream, blockMap.getBlocks(), maxLocals, blockMap.getLoopCount()); + liveness = LocalLiveness.compute(debug, stream, blockMap.getBlocks(), maxLocals, blockMap.getLoopCount()); } catch (Throwable e) { - throw Debug.handle(e); + throw debug.handle(e); } lastInstr = startInstruction; @@ -741,6 +796,8 @@ public class BytecodeParser implements GraphBuilderContext { } if (method.isSynchronized()) { + finishPrepare(lastInstr, BytecodeFrame.BEFORE_BCI); + // add a monitor enter to the start block methodSynchronizedObject = synchronizedObject(frameState, method); frameState.clearNonLiveLocals(startBlock, liveness, true); @@ -754,7 +811,7 @@ public class BytecodeParser implements GraphBuilderContext { profilingPlugin.profileInvoke(this, method, stateBefore); } - finishPrepare(lastInstr); + finishPrepare(lastInstr, 0); genInfoPointNode(InfopointReason.METHOD_START, null); @@ -770,10 +827,6 @@ public class BytecodeParser implements GraphBuilderContext { for (BciBlock block : blocks) { processBlock(block); } - - if (Debug.isDumpEnabled(Debug.INFO_LOG_LEVEL) && DumpDuringGraphBuilding.getValue() && this.beforeReturnNode != startInstruction) { - Debug.dump(Debug.INFO_LOG_LEVEL, graph, "Bytecodes parsed: %s.%s", method.getDeclaringClass().getUnqualifiedName(), method.getName()); - } } } @@ -800,11 +853,12 @@ public class BytecodeParser implements GraphBuilderContext { } /** - * Hook for subclasses to modify the graph start instruction or append new instructions to it. + * Hook for subclasses to modify synthetic code (start nodes and unwind nodes). * - * @param startInstr the start instruction of the graph + * @param instruction the current last instruction + * @param bci the current bci */ - protected void finishPrepare(FixedWithNextNode startInstr) { + protected void finishPrepare(FixedWithNextNode instruction, int bci) { } protected void cleanupFinalGraph() { @@ -823,46 +877,13 @@ public class BytecodeParser implements GraphBuilderContext { Node predecessor = beginNode.predecessor(); if (predecessor instanceof ControlSplitNode) { // The begin node is necessary. - } else { - if (beginNode.hasUsages()) { - reanchorGuardedNodes(beginNode); - } + } else if (!beginNode.hasUsages()) { GraphUtil.unlinkFixedNode(beginNode); beginNode.safeDelete(); } } } - /** - * Removes {@link GuardedNode}s from {@code beginNode}'s usages and re-attaches them to an - * appropriate preceeding {@link GuardingNode}. - */ - protected void reanchorGuardedNodes(BeginNode beginNode) { - // Find the new guarding node - GuardingNode guarding = null; - Node pred = beginNode.predecessor(); - while (pred != null) { - if (pred instanceof BeginNode) { - if (pred.predecessor() instanceof ControlSplitNode) { - guarding = (GuardingNode) pred; - break; - } - } else if (pred.getNodeClass().getAllowedUsageTypes().contains(InputType.Guard)) { - guarding = (GuardingNode) pred; - break; - } - pred = pred.predecessor(); - } - - // Reset the guard for all of beginNode's usages - for (Node usage : beginNode.usages().snapshot()) { - GuardedNode guarded = (GuardedNode) usage; - assert guarded.getGuard() == beginNode; - guarded.setGuard(guarding); - } - assert beginNode.hasNoUsages() : beginNode; - } - /** * Creates the frame state after the start node of a graph for an {@link IntrinsicContext * intrinsic} that is the parse root (either for root compiling or for post-parse inlining). @@ -922,7 +943,7 @@ public class BytecodeParser implements GraphBuilderContext { */ protected void handleUnresolvedCheckCast(JavaType type, ValueNode object) { assert !graphBuilderConfig.eagerResolving(); - append(new FixedGuardNode(graph.unique(IsNullNode.create(object)), Unresolved, InvalidateRecompile)); + append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(object)), Unresolved, InvalidateRecompile)); frameState.push(JavaKind.Object, appendConstant(JavaConstant.NULL_POINTER)); } @@ -934,7 +955,7 @@ public class BytecodeParser implements GraphBuilderContext { assert !graphBuilderConfig.eagerResolving(); AbstractBeginNode successor = graph.add(new BeginNode()); DeoptimizeNode deopt = graph.add(new DeoptimizeNode(InvalidateRecompile, Unresolved)); - append(new IfNode(graph.unique(IsNullNode.create(object)), successor, deopt, 1)); + append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(object)), successor, deopt, 1)); lastInstr = successor; frameState.push(JavaKind.Int, appendConstant(JavaConstant.INT_0)); } @@ -1003,7 +1024,7 @@ public class BytecodeParser implements GraphBuilderContext { private AbstractBeginNode handleException(ValueNode exceptionObject, int bci) { assert bci == BytecodeFrame.BEFORE_BCI || bci == bci() : "invalid bci"; - Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci))); + debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci))); FrameStateBuilder dispatchState = frameState.copy(); dispatchState.clearStack(); @@ -1092,15 +1113,15 @@ public class BytecodeParser implements GraphBuilderContext { } protected ValueNode genNegateOp(ValueNode x) { - return (new NegateNode(x)); + return NegateNode.create(x); } protected ValueNode genLeftShift(ValueNode x, ValueNode y) { - return new LeftShiftNode(x, y); + return LeftShiftNode.create(x, y); } protected ValueNode genRightShift(ValueNode x, ValueNode y) { - return new RightShiftNode(x, y); + return RightShiftNode.create(x, y); } protected ValueNode genUnsignedRightShift(ValueNode x, ValueNode y) { @@ -1120,7 +1141,7 @@ public class BytecodeParser implements GraphBuilderContext { } protected ValueNode genNormalizeCompare(ValueNode x, ValueNode y, boolean isUnorderedLess) { - return NormalizeCompareNode.create(x, y, isUnorderedLess, constantReflection); + return NormalizeCompareNode.create(x, y, isUnorderedLess, JavaKind.Int, constantReflection); } protected ValueNode genFloatConvert(FloatConvert op, ValueNode input) { @@ -1151,15 +1172,15 @@ public class BytecodeParser implements GraphBuilderContext { } protected LogicNode genObjectEquals(ValueNode x, ValueNode y) { - return ObjectEqualsNode.create(x, y, constantReflection); + return ObjectEqualsNode.create(constantReflection, metaAccess, options, x, y); } protected LogicNode genIntegerEquals(ValueNode x, ValueNode y) { - return IntegerEqualsNode.create(x, y, constantReflection); + return IntegerEqualsNode.create(constantReflection, metaAccess, options, null, x, y); } protected LogicNode genIntegerLessThan(ValueNode x, ValueNode y) { - return IntegerLessThanNode.create(x, y, constantReflection); + return IntegerLessThanNode.create(constantReflection, metaAccess, options, null, x, y); } protected ValueNode genUnique(ValueNode x) { @@ -1178,8 +1199,8 @@ public class BytecodeParser implements GraphBuilderContext { genInfoPointNode(InfopointReason.BYTECODE_POSITION, null); ValueNode exception = frameState.pop(JavaKind.Object); - FixedGuardNode nullCheck = append(new FixedGuardNode(graph.unique(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true)); - PiNode nonNullException = graph.unique(new PiNode(exception, exception.stamp().join(objectNonNull()), nullCheck)); + FixedGuardNode nullCheck = append(new FixedGuardNode(graph.addOrUniqueWithInputs(IsNullNode.create(exception)), NullCheckException, InvalidateReprofile, true)); + ValueNode nonNullException = graph.maybeAddOrUnique(PiNode.create(exception, exception.stamp().join(objectNonNull()), nullCheck)); lastInstr.setNext(handleException(nonNullException, bci())); } @@ -1204,7 +1225,7 @@ public class BytecodeParser implements GraphBuilderContext { } protected ValueNode genConditional(ValueNode x) { - return new ConditionalNode((LogicNode) x); + return ConditionalNode.create((LogicNode) x); } protected NewInstanceNode createNewInstance(ResolvedJavaType type, boolean fillContents) { @@ -1222,31 +1243,38 @@ public class BytecodeParser implements GraphBuilderContext { protected ValueNode genLoadField(ValueNode receiver, ResolvedJavaField field) { StampPair stamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, field.getType(), false); if (stamp == null) { - return LoadFieldNode.create(this.graph.getAssumptions(), receiver, field); + return LoadFieldNode.create(getConstantFieldProvider(), getConstantReflection(), getMetaAccess(), getOptions(), + getAssumptions(), receiver, field, false, false); } else { - return LoadFieldNode.createOverrideStamp(stamp, receiver, field); + return LoadFieldNode.createOverrideStamp(getConstantFieldProvider(), getConstantReflection(), getMetaAccess(), getOptions(), + stamp, receiver, field, false, false); } } + protected StateSplitProxyNode genVolatileFieldReadProxy(ValueNode fieldRead) { + return new StateSplitProxyNode(fieldRead); + } + protected ValueNode emitExplicitNullCheck(ValueNode receiver) { if (StampTool.isPointerNonNull(receiver.stamp())) { return receiver; } BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, NullPointerException.class)); AbstractBeginNode falseSucc = graph.add(new BeginNode()); - PiNode nonNullReceiver = graph.unique(new PiNode(receiver, receiver.stamp().join(objectNonNull()), falseSucc)); - append(new IfNode(graph.unique(IsNullNode.create(receiver)), exception, falseSucc, 0.01)); + ValueNode nonNullReceiver = graph.addOrUnique(PiNode.create(receiver, objectNonNull(), falseSucc)); + append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(receiver)), exception, falseSucc, SLOW_PATH_PROBABILITY)); lastInstr = falseSucc; exception.setStateAfter(createFrameState(bci(), exception)); exception.setNext(handleException(exception, bci())); + EXPLICIT_EXCEPTIONS.increment(debug); return nonNullReceiver; } protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) { AbstractBeginNode trueSucc = graph.add(new BeginNode()); BytecodeExceptionNode exception = graph.add(new BytecodeExceptionNode(metaAccess, ArrayIndexOutOfBoundsException.class, index)); - append(new IfNode(graph.unique(IntegerBelowNode.create(index, length, constantReflection)), trueSucc, exception, 0.99)); + append(new IfNode(genUnique(IntegerBelowNode.create(constantReflection, metaAccess, options, null, index, length)), trueSucc, exception, FAST_PATH_PROBABILITY)); lastInstr = trueSucc; exception.setStateAfter(createFrameState(bci(), exception)); @@ -1283,7 +1311,7 @@ public class BytecodeParser implements GraphBuilderContext { if (callTargetIsResolved(target)) { ResolvedJavaMethod resolvedTarget = (ResolvedJavaMethod) target; ResolvedJavaType holder = resolvedTarget.getDeclaringClass(); - if (!holder.isInitialized() && ResolveClassBeforeStaticInvoke.getValue()) { + if (!holder.isInitialized() && ResolveClassBeforeStaticInvoke.getValue(options)) { handleUnresolvedInvoke(target, InvokeKind.Static); } else { ValueNode classInit = null; @@ -1361,8 +1389,19 @@ public class BytecodeParser implements GraphBuilderContext { } } - private InvokeKind currentInvokeKind; - private JavaType currentInvokeReturnType; + static class CurrentInvoke { + final ValueNode[] args; + final InvokeKind kind; + final JavaType returnType; + + CurrentInvoke(ValueNode[] args, InvokeKind kind, JavaType returnType) { + this.args = args; + this.kind = kind; + this.returnType = returnType; + } + } + + private CurrentInvoke currentInvoke; protected FrameStateBuilder frameState; protected BciBlock currentBlock; protected final BytecodeStream stream; @@ -1381,12 +1420,12 @@ public class BytecodeParser implements GraphBuilderContext { @Override public InvokeKind getInvokeKind() { - return currentInvokeKind; + return currentInvoke == null ? null : currentInvoke.kind; } @Override public JavaType getInvokeReturnType() { - return currentInvokeReturnType; + return currentInvoke == null ? null : currentInvoke.returnType; } private boolean forceInliningEverything; @@ -1402,7 +1441,14 @@ public class BytecodeParser implements GraphBuilderContext { } } - private Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) { + @Override + public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) { + BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor(); + boolean withExceptionEdge = intrinsicCallSiteParser == null ? !omitInvokeExceptionEdge(null) : !intrinsicCallSiteParser.omitInvokeExceptionEdge(null); + createNonInlinedInvoke(withExceptionEdge, bci(), callTarget, resultType); + } + + protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod initialTargetMethod, ValueNode[] args) { ResolvedJavaMethod targetMethod = initialTargetMethod; InvokeKind invokeKind = initialInvokeKind; if (initialInvokeKind.isIndirect()) { @@ -1415,7 +1461,7 @@ public class BytecodeParser implements GraphBuilderContext { } JavaKind resultType = targetMethod.getSignature().getReturnKind(); - if (DeoptALot.getValue()) { + if (!parsingIntrinsic() && DeoptALot.getValue(options)) { append(new DeoptimizeNode(DeoptimizationAction.None, RuntimeConstraint)); frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, graph)); return null; @@ -1426,28 +1472,31 @@ public class BytecodeParser implements GraphBuilderContext { returnType = returnType.resolve(targetMethod.getDeclaringClass()); } if (invokeKind.hasReceiver()) { - args[0] = emitExplicitExceptions(args[0], null); + args[0] = emitExplicitExceptions(args[0]); + } - if (args[0].isNullConstant()) { - append(new DeoptimizeNode(InvalidateRecompile, NullCheckException)); - return null; - } + if (initialInvokeKind == InvokeKind.Special && !targetMethod.isConstructor()) { + emitCheckForInvokeSuperSpecial(args); } InlineInfo inlineInfo = null; try { - currentInvokeReturnType = returnType; - currentInvokeKind = invokeKind; + currentInvoke = new CurrentInvoke(args, invokeKind, returnType); if (tryNodePluginForInvocation(args, targetMethod)) { - if (TraceParserPlugins.getValue()) { + if (TraceParserPlugins.getValue(options)) { traceWithContext("used node plugin for %s", targetMethod.format("%h.%n(%p)")); } return null; } - if (!invokeKind.isIndirect() || (UseGuardedIntrinsics.getValue() && !GeneratePIC.getValue())) { + if (invokeKind.hasReceiver() && args[0].isNullConstant()) { + append(new DeoptimizeNode(InvalidateRecompile, NullCheckException)); + return null; + } + + if (!invokeKind.isIndirect() || (UseGuardedIntrinsics.getValue(options) && !GeneratePIC.getValue(options))) { if (tryInvocationPlugin(invokeKind, args, targetMethod, resultType, returnType)) { - if (TraceParserPlugins.getValue()) { + if (TraceParserPlugins.getValue(options)) { traceWithContext("used invocation plugin for %s", targetMethod.format("%h.%n(%p)")); } return null; @@ -1461,36 +1510,123 @@ public class BytecodeParser implements GraphBuilderContext { } } } finally { - currentInvokeReturnType = null; - currentInvokeKind = null; + currentInvoke = null; } - JavaTypeProfile profile = null; - if (invokeKind.isIndirect() && profilingInfo != null && this.optimisticOpts.useTypeCheckHints()) { - profile = profilingInfo.getTypeProfile(bci()); + int invokeBci = bci(); + JavaTypeProfile profile = getProfileForInvoke(invokeKind); + boolean withExceptionEdge = !omitInvokeExceptionEdge(inlineInfo); + boolean partialIntrinsicExit = false; + if (intrinsicContext != null && intrinsicContext.isCallToOriginal(targetMethod)) { + partialIntrinsicExit = true; + ResolvedJavaMethod originalMethod = intrinsicContext.getOriginalMethod(); + BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor(); + if (intrinsicCallSiteParser != null) { + // When exiting a partial intrinsic, the invoke to the original + // must use the same context as the call to the intrinsic. + invokeBci = intrinsicCallSiteParser.bci(); + profile = intrinsicCallSiteParser.getProfileForInvoke(invokeKind); + withExceptionEdge = !intrinsicCallSiteParser.omitInvokeExceptionEdge(inlineInfo); + } else { + // We are parsing the intrinsic for the root compilation or for inlining, + // This call is a partial intrinsic exit, and we do not have profile information + // for this callsite. We also have to assume that the call needs an exception + // edge. Finally, we know that this intrinsic is parsed for late inlining, + // so the bci must be set to unknown, so that the inliner patches it later. + assert intrinsicContext.isPostParseInlined(); + invokeBci = BytecodeFrame.UNKNOWN_BCI; + profile = null; + withExceptionEdge = graph.method().getAnnotation(Snippet.class) == null; + } + + if (originalMethod.isStatic()) { + invokeKind = InvokeKind.Static; + } else { + // The original call to the intrinsic must have been devirtualized + // otherwise we wouldn't be here. + invokeKind = InvokeKind.Special; + } + Signature sig = originalMethod.getSignature(); + returnType = sig.getReturnType(method.getDeclaringClass()); + resultType = sig.getReturnKind(); + assert checkPartialIntrinsicExit(intrinsicCallSiteParser == null ? null : intrinsicCallSiteParser.currentInvoke.args, args); + targetMethod = originalMethod; } - return createNonInlinedInvoke(args, targetMethod, invokeKind, resultType, returnType, inlineInfo, profile); + Invoke invoke = createNonInlinedInvoke(withExceptionEdge, invokeBci, args, targetMethod, invokeKind, resultType, returnType, profile); + if (partialIntrinsicExit) { + // This invoke must never be later inlined as it might select the intrinsic graph. + // Until there is a mechanism to guarantee that any late inlining will not select + // the intrinsic graph, prevent this invoke from being inlined. + invoke.setUseForInlining(false); + } + return invoke; } - protected Invoke createNonInlinedInvoke(ValueNode[] args, ResolvedJavaMethod targetMethod, InvokeKind invokeKind, - JavaKind resultType, JavaType returnType, InlineInfo inlineInfo, JavaTypeProfile profile) { + /** + * Checks that the class of the receiver of an {@link Bytecodes#INVOKESPECIAL} in a method + * declared in an interface (i.e., a default method) is assignable to the interface. If not, + * then deoptimize so that the interpreter can throw an {@link IllegalAccessError}. + * + * This is a check not performed by the verifier and so must be performed at runtime. + * + * @param args arguments to an {@link Bytecodes#INVOKESPECIAL} implementing a direct call to a + * method in a super class + */ + protected void emitCheckForInvokeSuperSpecial(ValueNode[] args) { + ResolvedJavaType callingClass = method.getDeclaringClass(); + if (callingClass.getHostClass() != null) { + callingClass = callingClass.getHostClass(); + } + if (callingClass.isInterface()) { + ValueNode receiver = args[0]; + TypeReference checkedType = TypeReference.createTrusted(graph.getAssumptions(), callingClass); + LogicNode condition = genUnique(createInstanceOf(checkedType, receiver, null)); + FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, ClassCastException, None, false)); + args[0] = append(PiNode.create(receiver, StampFactory.object(checkedType, true), fixedGuard)); + } + } + + protected JavaTypeProfile getProfileForInvoke(InvokeKind invokeKind) { + if (invokeKind.isIndirect() && profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) { + return profilingInfo.getTypeProfile(bci()); + } + return null; + } + + /** + * A partial intrinsic exits by (effectively) calling the intrinsified method. This call must + * use exactly the arguments to the call being intrinsified. + * + * @param originalArgs arguments of original call to intrinsified method + * @param recursiveArgs arguments of recursive call to intrinsified method + */ + private static boolean checkPartialIntrinsicExit(ValueNode[] originalArgs, ValueNode[] recursiveArgs) { + if (originalArgs != null) { + for (int i = 0; i < originalArgs.length; i++) { + ValueNode arg = GraphUtil.unproxify(recursiveArgs[i]); + ValueNode icArg = GraphUtil.unproxify(originalArgs[i]); + assert arg == icArg : String.format("argument %d of call denoting partial intrinsic exit should be %s, not %s", i, icArg, arg); + } + } else { + for (int i = 0; i < recursiveArgs.length; i++) { + ValueNode arg = GraphUtil.unproxify(recursiveArgs[i]); + assert arg instanceof ParameterNode && ((ParameterNode) arg).index() == i : String.format("argument %d of call denoting partial intrinsic exit should be a %s with index %d, not %s", i, + ParameterNode.class.getSimpleName(), i, arg); + } + } + return true; + } + + protected Invoke createNonInlinedInvoke(boolean withExceptionEdge, int invokeBci, ValueNode[] invokeArgs, ResolvedJavaMethod targetMethod, + InvokeKind invokeKind, JavaKind resultType, JavaType returnType, JavaTypeProfile profile) { StampPair returnStamp = graphBuilderConfig.getPlugins().getOverridingStamp(this, returnType, false); if (returnStamp == null) { returnStamp = StampFactory.forDeclaredType(graph.getAssumptions(), returnType, false); } - MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, targetMethod, args, returnStamp, profile)); - - Invoke invoke; - if (omitInvokeExceptionEdge(callTarget, inlineInfo)) { - invoke = createInvoke(callTarget, resultType); - } else { - invoke = createInvokeWithException(callTarget, resultType); - AbstractBeginNode beginNode = graph.add(new KillingBeginNode(LocationIdentity.any())); - invoke.setNext(beginNode); - lastInstr = beginNode; - } + MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, targetMethod, invokeArgs, returnStamp, profile)); + Invoke invoke = createNonInlinedInvoke(withExceptionEdge, invokeBci, callTarget, resultType); for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) { plugin.notifyNotInlined(this, targetMethod, invoke); @@ -1499,26 +1635,48 @@ public class BytecodeParser implements GraphBuilderContext { return invoke; } + protected Invoke createNonInlinedInvoke(boolean withExceptionEdge, int invokeBci, CallTargetNode callTarget, JavaKind resultType) { + if (!withExceptionEdge) { + return createInvoke(invokeBci, callTarget, resultType); + } else { + Invoke invoke = createInvokeWithException(invokeBci, callTarget, resultType); + AbstractBeginNode beginNode = graph.add(KillingBeginNode.create(LocationIdentity.any())); + invoke.setNext(beginNode); + lastInstr = beginNode; + return invoke; + } + } + /** * If the method returns true, the invocation of the given {@link MethodCallTargetNode call * target} does not need an exception edge. - * - * @param callTarget The call target. */ - protected boolean omitInvokeExceptionEdge(MethodCallTargetNode callTarget, InlineInfo lastInlineInfo) { + protected boolean omitInvokeExceptionEdge(InlineInfo lastInlineInfo) { if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION) { return false; } else if (lastInlineInfo == InlineInfo.DO_NOT_INLINE_NO_EXCEPTION) { return true; } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.CheckAll) { return false; + } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.ExplicitOnly) { + return false; } else if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.OmitAll) { return true; } else { assert graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.Profile; // be conservative if information was not recorded (could result in endless // recompiles otherwise) - return (!StressInvokeWithExceptionNode.getValue() && optimisticOpts.useExceptionProbability() && profilingInfo != null && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE); + if (!StressInvokeWithExceptionNode.getValue(options)) { + if (optimisticOpts.useExceptionProbability(getOptions())) { + if (profilingInfo != null) { + TriState exceptionSeen = profilingInfo.getExceptionSeen(bci()); + if (exceptionSeen == TriState.FALSE) { + return true; + } + } + } + } + return false; } } @@ -1537,7 +1695,7 @@ public class BytecodeParser implements GraphBuilderContext { final Mark mark; InvocationPluginAssertions(InvocationPlugin plugin, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType) { - guarantee(assertionsEnabled(), "%s should only be loaded and instantiated if assertions are enabled", getClass().getSimpleName()); + guarantee(Assertions.assertionsEnabled(), "%s should only be loaded and instantiated if assertions are enabled", getClass().getSimpleName()); this.plugin = plugin; this.targetMethod = targetMethod; this.args = args; @@ -1622,7 +1780,7 @@ public class BytecodeParser implements GraphBuilderContext { receiverType = targetMethod.getDeclaringClass(); } ResolvedJavaMethod resolvedMethod = receiverType.resolveMethod(targetMethod, method.getDeclaringClass()); - if (resolvedMethod == null || resolvedMethod == targetMethod) { + if (resolvedMethod == null || resolvedMethod.equals(targetMethod)) { assert resolvedMethod == null || targetMethod.getDeclaringClass().isAssignableFrom(resolvedMethod.getDeclaringClass()); Mark mark = graph.getMark(); FixedWithNextNode currentLastInstr = lastInstr; @@ -1631,10 +1789,10 @@ public class BytecodeParser implements GraphBuilderContext { LoadHubNode hub = graph.unique(new LoadHubNode(stampProvider, nonNullReceiver)); LoadMethodNode actual = append(new LoadMethodNode(methodStamp, targetMethod, receiverType, method.getDeclaringClass(), hub)); ConstantNode expected = graph.unique(ConstantNode.forConstant(methodStamp, targetMethod.getEncoding(), getMetaAccess())); - LogicNode compare = graph.unique(CompareNode.createCompareNode(Condition.EQ, actual, expected, constantReflection)); + LogicNode compare = graph.addOrUniqueWithInputs(CompareNode.createCompareNode(constantReflection, metaAccess, options, null, Condition.EQ, actual, expected)); JavaTypeProfile profile = null; - if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints()) { + if (profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) { profile = profilingInfo.getTypeProfile(bci()); if (profile != null) { JavaTypeProfile newProfile = adjustProfileForInvocationPlugin(profile, targetMethod); @@ -1655,7 +1813,7 @@ public class BytecodeParser implements GraphBuilderContext { AbstractBeginNode intrinsicBranch = graph.add(new BeginNode()); AbstractBeginNode nonIntrinsicBranch = graph.add(new BeginNode()); - append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, 0.01)); + append(new IfNode(compare, intrinsicBranch, nonIntrinsicBranch, FAST_PATH_PROBABILITY)); lastInstr = intrinsicBranch; return new IntrinsicGuard(currentLastInstr, intrinsicReceiver, mark, nonIntrinsicBranch, profile); } else { @@ -1697,15 +1855,15 @@ public class BytecodeParser implements GraphBuilderContext { /** * Performs any action required after execution of an invocation plugin. This includes - * {@linkplain InvocationPluginAssertions#check(boolean) checking} invocation plugin invariants - * as well as weaving the {@code else} branch of the code woven by {@link #guardIntrinsic} if + * {@linkplain InvocationPluginAssertions#check checking} invocation plugin invariants as well + * as weaving the {@code else} branch of the code woven by {@link #guardIntrinsic} if * {@code guard != null}. */ - protected void afterInvocationPluginExecution(boolean pluginResult, InvocationPluginAssertions assertions, IntrinsicGuard intrinsicGuard, + protected void afterInvocationPluginExecution(boolean pluginHandledInvoke, InvocationPluginAssertions assertions, IntrinsicGuard intrinsicGuard, InvokeKind invokeKind, ValueNode[] args, ResolvedJavaMethod targetMethod, JavaKind resultType, JavaType returnType) { - assert assertions.check(pluginResult); + assert assertions.check(pluginHandledInvoke); if (intrinsicGuard != null) { - if (pluginResult) { + if (pluginHandledInvoke) { if (intrinsicGuard.nonIntrinsicBranch != null) { // Intrinsic emitted: emit a virtual call to the target method and // merge it with the intrinsic branch @@ -1720,7 +1878,7 @@ public class BytecodeParser implements GraphBuilderContext { } lastInstr = intrinsicGuard.nonIntrinsicBranch; - createNonInlinedInvoke(args, targetMethod, invokeKind, resultType, returnType, null, intrinsicGuard.profile); + createNonInlinedInvoke(omitInvokeExceptionEdge(null), bci(), args, targetMethod, invokeKind, resultType, returnType, intrinsicGuard.profile); EndNode nonIntrinsicEnd = append(new EndNode()); AbstractMergeNode mergeNode = graph.add(new MergeNode()); @@ -1769,7 +1927,7 @@ public class BytecodeParser implements GraphBuilderContext { } } - InvocationPluginAssertions assertions = assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null; + InvocationPluginAssertions assertions = Assertions.assertionsEnabled() ? new InvocationPluginAssertions(plugin, args, targetMethod, resultType) : null; if (plugin.execute(this, targetMethod, pluginReceiver, args)) { afterInvocationPluginExecution(true, assertions, intrinsicGuard, invokeKind, args, targetMethod, resultType, returnType); return true; @@ -1817,14 +1975,53 @@ public class BytecodeParser implements GraphBuilderContext { if (inline(targetMethod, inlineInfo.getMethodToInline(), inlineInfo.getIntrinsicBytecodeProvider(), args)) { return SUCCESSFULLY_INLINED; } + inlineInfo = null; } /* Do not inline, and do not ask the remaining plugins. */ return inlineInfo; } } + + // There was no inline plugin with a definite answer to whether or not + // to inline. If we're parsing an intrinsic, then we need to enforce the + // invariant here that methods are always force inlined in intrinsics/snippets. + if (parsingIntrinsic()) { + if (inline(targetMethod, targetMethod, this.bytecodeProvider, args)) { + return SUCCESSFULLY_INLINED; + } + } return null; } + private static final int ACCESSOR_BYTECODE_LENGTH = 5; + + /** + * Tries to inline {@code targetMethod} if it is an instance field accessor. This avoids the + * overhead of creating and using a nested {@link BytecodeParser} object. + */ + private boolean tryFastInlineAccessor(ValueNode[] args, ResolvedJavaMethod targetMethod) { + byte[] bytecode = targetMethod.getCode(); + if (bytecode != null && bytecode.length == ACCESSOR_BYTECODE_LENGTH && + Bytes.beU1(bytecode, 0) == ALOAD_0 && + Bytes.beU1(bytecode, 1) == GETFIELD) { + int b4 = Bytes.beU1(bytecode, 4); + if (b4 >= IRETURN && b4 <= ARETURN) { + int cpi = Bytes.beU2(bytecode, 2); + JavaField field = targetMethod.getConstantPool().lookupField(cpi, targetMethod, GETFIELD); + if (field instanceof ResolvedJavaField) { + ValueNode receiver = invocationPluginReceiver.init(targetMethod, args).get(); + ResolvedJavaField resolvedField = (ResolvedJavaField) field; + genGetField(resolvedField, receiver); + notifyBeforeInline(targetMethod); + printInlining(targetMethod, targetMethod, true, "inline accessor method (bytecode parsing)"); + notifyAfterInline(targetMethod); + return true; + } + } + } + return false; + } + @Override public boolean intrinsify(BytecodeProvider intrinsicBytecodeProvider, ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, InvocationPlugin.Receiver receiver, ValueNode[] args) { if (receiver != null) { @@ -1836,14 +2033,15 @@ public class BytecodeParser implements GraphBuilderContext { } private boolean inline(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, BytecodeProvider intrinsicBytecodeProvider, ValueNode[] args) { - if (TraceInlineDuringParsing.getValue() || TraceParserPlugins.getValue()) { - if (targetMethod.equals(inlinedMethod)) { - traceWithContext("inlining call to %s", inlinedMethod.format("%h.%n(%p)")); - } else { - traceWithContext("inlining call to %s as intrinsic for %s", inlinedMethod.format("%h.%n(%p)"), targetMethod.format("%h.%n(%p)")); - } - } IntrinsicContext intrinsic = this.intrinsicContext; + + if (intrinsic == null && !graphBuilderConfig.insertFullInfopoints() && + targetMethod.equals(inlinedMethod) && + (targetMethod.getModifiers() & (STATIC | SYNCHRONIZED)) == 0 && + tryFastInlineAccessor(args, targetMethod)) { + return true; + } + if (intrinsic != null && intrinsic.isCallToOriginal(targetMethod)) { if (intrinsic.isCompilationRoot()) { // A root compiled intrinsic needs to deoptimize @@ -1854,16 +2052,23 @@ public class BytecodeParser implements GraphBuilderContext { printInlining(targetMethod, inlinedMethod, true, "compilation root (bytecode parsing)"); return true; } else { - // Otherwise inline the original method. Any frame state created - // during the inlining will exclude frame(s) in the - // intrinsic method (see HIRFrameStateBuilder.create(int bci)). if (intrinsic.getOriginalMethod().isNative()) { printInlining(targetMethod, inlinedMethod, false, "native method (bytecode parsing)"); return false; } - printInlining(targetMethod, inlinedMethod, true, "inline intrinsic (bytecode parsing)"); - parseAndInlineCallee(intrinsic.getOriginalMethod(), args, null); - return true; + if (canInlinePartialIntrinsicExit() && InlinePartialIntrinsicExitDuringParsing.getValue(options)) { + // Otherwise inline the original method. Any frame state created + // during the inlining will exclude frame(s) in the + // intrinsic method (see FrameStateBuilder.create(int bci)). + notifyBeforeInline(inlinedMethod); + printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)"); + parseAndInlineCallee(intrinsic.getOriginalMethod(), args, null); + notifyAfterInline(inlinedMethod); + return true; + } else { + printInlining(targetMethod, inlinedMethod, false, "partial intrinsic exit (bytecode parsing)"); + return false; + } } } else { boolean isIntrinsic = intrinsicBytecodeProvider != null; @@ -1872,14 +2077,10 @@ public class BytecodeParser implements GraphBuilderContext { intrinsic = new IntrinsicContext(targetMethod, inlinedMethod, intrinsicBytecodeProvider, INLINE_DURING_PARSING); } if (inlinedMethod.hasBytecodes()) { - for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) { - plugin.notifyBeforeInline(inlinedMethod); - } + notifyBeforeInline(inlinedMethod); printInlining(targetMethod, inlinedMethod, true, "inline method (bytecode parsing)"); parseAndInlineCallee(inlinedMethod, args, intrinsic); - for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) { - plugin.notifyAfterInline(inlinedMethod); - } + notifyAfterInline(inlinedMethod); } else { printInlining(targetMethod, inlinedMethod, false, "no bytecodes (abstract or native) (bytecode parsing)"); return false; @@ -1888,8 +2089,37 @@ public class BytecodeParser implements GraphBuilderContext { return true; } + protected void notifyBeforeInline(ResolvedJavaMethod inlinedMethod) { + for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) { + plugin.notifyBeforeInline(inlinedMethod); + } + } + + protected void notifyAfterInline(ResolvedJavaMethod inlinedMethod) { + for (InlineInvokePlugin plugin : graphBuilderConfig.getPlugins().getInlineInvokePlugins()) { + plugin.notifyAfterInline(inlinedMethod); + } + } + + /** + * Determines if a partial intrinsic exit (i.e., a call to the original method within an + * intrinsic) can be inlined. + */ + protected boolean canInlinePartialIntrinsicExit() { + return true; + } + private void printInlining(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, boolean success, String msg) { - if (GraalOptions.HotSpotPrintInlining.getValue()) { + if (success) { + if (TraceInlineDuringParsing.getValue(options) || TraceParserPlugins.getValue(options)) { + if (targetMethod.equals(inlinedMethod)) { + traceWithContext("inlining call to %s", inlinedMethod.format("%h.%n(%p)")); + } else { + traceWithContext("inlining call to %s as intrinsic for %s", inlinedMethod.format("%h.%n(%p)"), targetMethod.format("%h.%n(%p)")); + } + } + } + if (HotSpotPrintInlining.getValue(options)) { if (targetMethod.equals(inlinedMethod)) { Util.printInlining(inlinedMethod, bci(), getDepth(), success, "%s", msg); } else { @@ -1914,8 +2144,9 @@ public class BytecodeParser implements GraphBuilderContext { protected void traceWithContext(String format, Object... args) { StackTraceElement where = code.asStackTraceElement(bci()); - TTY.println(format("%s%s (%s:%d) %s", nSpaces(getDepth()), method.isConstructor() ? method.format("%h.%n") : method.getName(), where.getFileName(), where.getLineNumber(), - format(format, args))); + String s = format("%s%s (%s:%d) %s", nSpaces(getDepth()), method.isConstructor() ? method.format("%h.%n") : method.getName(), where.getFileName(), where.getLineNumber(), + format(format, args)); + TTY.println(s); } protected BytecodeParserError asParserError(Throwable e) { @@ -1931,7 +2162,6 @@ public class BytecodeParser implements GraphBuilderContext { return res; } - @SuppressWarnings("try") protected void parseAndInlineCallee(ResolvedJavaMethod targetMethod, ValueNode[] args, IntrinsicContext calleeIntrinsicContext) { try (IntrinsicScope s = calleeIntrinsicContext != null && !parsingIntrinsic() ? new IntrinsicScope(this, targetMethod.getSignature().toParameterKinds(!targetMethod.isStatic()), args) : null) { @@ -1943,13 +2173,41 @@ public class BytecodeParser implements GraphBuilderContext { startFrameState.initializeFromArgumentsArray(args); parser.build(this.lastInstr, startFrameState); - FixedWithNextNode calleeBeforeReturnNode = parser.getBeforeReturnNode(); - this.lastInstr = calleeBeforeReturnNode; - JavaKind calleeReturnKind = targetMethod.getSignature().getReturnKind(); - if (calleeBeforeReturnNode != null) { - ValueNode calleeReturnValue = parser.getReturnValue(); + if (parser.returnDataList == null) { + /* Callee does not return. */ + lastInstr = null; + } else { + ValueNode calleeReturnValue; + MergeNode returnMergeNode = null; + if (s != null) { + s.returnDataList = parser.returnDataList; + } + if (parser.returnDataList.size() == 1) { + /* Callee has a single return, we can continue parsing at that point. */ + ReturnToCallerData singleReturnData = parser.returnDataList.get(0); + lastInstr = singleReturnData.beforeReturnNode; + calleeReturnValue = singleReturnData.returnValue; + } else { + assert parser.returnDataList.size() > 1; + /* Callee has multiple returns, we need to insert a control flow merge. */ + returnMergeNode = graph.add(new MergeNode()); + calleeReturnValue = ValueMergeUtil.mergeValueProducers(returnMergeNode, parser.returnDataList, returnData -> returnData.beforeReturnNode, returnData -> returnData.returnValue); + } + if (calleeReturnValue != null) { - frameState.push(calleeReturnKind.getStackKind(), calleeReturnValue); + frameState.push(targetMethod.getSignature().getReturnKind().getStackKind(), calleeReturnValue); + } + if (returnMergeNode != null) { + returnMergeNode.setStateAfter(createFrameState(stream.nextBCI(), returnMergeNode)); + lastInstr = finishInstruction(returnMergeNode, frameState); + } + } + /* + * Propagate any side effects into the caller when parsing intrinsics. + */ + if (parser.frameState.isAfterSideEffect() && parsingIntrinsic()) { + for (StateSplit sideEffect : parser.frameState.sideEffects()) { + frameState.addSideEffect(sideEffect); } } @@ -1966,14 +2224,14 @@ public class BytecodeParser implements GraphBuilderContext { return new MethodCallTargetNode(invokeKind, targetMethod, args, returnStamp, profile); } - protected InvokeNode createInvoke(CallTargetNode callTarget, JavaKind resultType) { - InvokeNode invoke = append(new InvokeNode(callTarget, bci())); + protected InvokeNode createInvoke(int invokeBci, CallTargetNode callTarget, JavaKind resultType) { + InvokeNode invoke = append(new InvokeNode(callTarget, invokeBci)); frameState.pushReturn(resultType, invoke); invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke)); return invoke; } - protected InvokeWithExceptionNode createInvokeWithException(CallTargetNode callTarget, JavaKind resultType) { + protected InvokeWithExceptionNode createInvokeWithException(int invokeBci, CallTargetNode callTarget, JavaKind resultType) { if (currentBlock != null && stream.nextBCI() > currentBlock.endBci) { /* * Clear non-live locals early so that the exception handler entry gets the cleared @@ -1983,7 +2241,7 @@ public class BytecodeParser implements GraphBuilderContext { } AbstractBeginNode exceptionEdge = handleException(null, bci()); - InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, bci())); + InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionEdge, invokeBci)); frameState.pushReturn(resultType, invoke); invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke)); return invoke; @@ -2012,27 +2270,18 @@ public class BytecodeParser implements GraphBuilderContext { } } } + + frameState.setRethrowException(false); + frameState.clearStack(); + beforeReturn(returnVal, returnKind); if (parent == null) { - frameState.setRethrowException(false); - frameState.clearStack(); - beforeReturn(returnVal, returnKind); append(new ReturnNode(returnVal)); } else { - if (blockMap.getReturnCount() == 1 || !controlFlowSplit) { - // There is only a single return. - beforeReturn(returnVal, returnKind); - this.returnValue = returnVal; - this.beforeReturnNode = this.lastInstr; - this.lastInstr = null; - } else { - frameState.setRethrowException(false); - frameState.clearStack(); - if (returnVal != null) { - frameState.push(returnKind, returnVal); - } - assert blockMap.getReturnCount() > 1; - appendGoto(blockMap.getReturnBlock()); + if (returnDataList == null) { + returnDataList = new ArrayList<>(); } + returnDataList.add(new ReturnToCallerData(returnVal, lastInstr)); + lastInstr = null; } } @@ -2051,7 +2300,11 @@ public class BytecodeParser implements GraphBuilderContext { genInfoPointNode(InfopointReason.METHOD_END, x); if (finalBarrierRequired) { assert originalReceiver != null; - append(new FinalFieldBarrierNode(originalReceiver)); + /* + * When compiling an OSR with a final field store, don't bother tracking the original + * receiver since the receiver cannot be EA'ed. + */ + append(new FinalFieldBarrierNode(entryBCI == INVOCATION_ENTRY_BCI ? originalReceiver : null)); } synchronizedEpilogue(BytecodeFrame.AFTER_BCI, x, kind); } @@ -2076,7 +2329,7 @@ public class BytecodeParser implements GraphBuilderContext { if (GraphUtil.originalValue(lockedObject) != GraphUtil.originalValue(x)) { throw bailout(String.format("unbalanced monitors: mismatch at monitorexit, %s != %s", GraphUtil.originalValue(x), GraphUtil.originalValue(lockedObject))); } - MonitorExitNode monitorExit = append(new MonitorExitNode(x, monitorId, escapedReturnValue)); + MonitorExitNode monitorExit = append(new MonitorExitNode(lockedObject, monitorId, escapedReturnValue)); monitorExit.setStateAfter(createFrameState(bci, monitorExit)); } @@ -2102,8 +2355,8 @@ public class BytecodeParser implements GraphBuilderContext { JsrScope scope = currentBlock.getJsrScope(); int retAddress = scope.nextReturnAddress(); ConstantNode returnBciNode = getJsrConstant(retAddress); - LogicNode guard = IntegerEqualsNode.create(local, returnBciNode, constantReflection); - guard = graph.unique(guard); + LogicNode guard = IntegerEqualsNode.create(constantReflection, metaAccess, options, null, local, returnBciNode); + guard = graph.addOrUniqueWithInputs(guard); append(new FixedGuardNode(guard, JavaSubroutineMismatch, InvalidateReprofile)); if (!successor.getJsrScope().equals(scope.pop())) { throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)"); @@ -2159,18 +2412,6 @@ public class BytecodeParser implements GraphBuilderContext { @Override public T append(T v) { - if (v.graph() != null) { - return v; - } - T added = graph.addOrUnique(v); - if (added == v) { - updateLastInstruction(v); - } - return added; - } - - @Override - public T recursiveAppend(T v) { if (v.graph() != null) { return v; } @@ -2182,25 +2423,6 @@ public class BytecodeParser implements GraphBuilderContext { } private void updateLastInstruction(T v) { - if (UseGraalInstrumentation.getValue()) { - // resolve instrumentation target - if (v instanceof InstrumentationBeginNode) { - InstrumentationBeginNode begin = (InstrumentationBeginNode) v; - if (!begin.isAnchored() && lastBCI != -1) { - int currentBCI = stream.currentBCI(); - // temporarily set the bytecode stream to lastBCI - stream.setBCI(lastBCI); - // The instrumentation should be associated with the predecessor. In case of the - // predecessor being optimized away, e.g., inlining, we should not set the - // target. - if (stream.nextBCI() == currentBCI) { - begin.setTarget(lastInstr); - } - // restore the current BCI - stream.setBCI(currentBCI); - } - } - } if (v instanceof FixedNode) { FixedNode fixedNode = (FixedNode) v; lastInstr.setNext(fixedNode); @@ -2208,10 +2430,8 @@ public class BytecodeParser implements GraphBuilderContext { FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) fixedNode; assert fixedWithNextNode.next() == null : "cannot append instruction to instruction which isn't end"; lastInstr = fixedWithNextNode; - lastBCI = stream.currentBCI(); } else { lastInstr = null; - lastBCI = -1; } } } @@ -2257,7 +2477,7 @@ public class BytecodeParser implements GraphBuilderContext { firstLoopExit = loopExit; } lastLoopExit = loopExit; - Debug.log("Target %s Exits %s, scanning framestates...", targetBlock, loop); + debug.log("Target %s Exits %s, scanning framestates...", targetBlock, loop); newState.clearNonLiveLocals(targetBlock, liveness, true); newState.insertLoopProxies(loopExit, getEntryState(loop)); loopExit.setStateAfter(newState.create(bci, loopExit)); @@ -2323,7 +2543,7 @@ public class BytecodeParser implements GraphBuilderContext { setEntryState(block, currentEntryState); currentEntryState.clearNonLiveLocals(block, liveness, true); - Debug.log("createTarget %s: first visit, result: %s", block, targetNode); + debug.log("createTarget %s: first visit, result: %s", block, targetNode); return result; } @@ -2344,7 +2564,7 @@ public class BytecodeParser implements GraphBuilderContext { FixedNode result = target.fixed; getEntryState(block).merge(loopBegin, target.state); - Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result); + debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result); return result; } assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch"; @@ -2385,7 +2605,7 @@ public class BytecodeParser implements GraphBuilderContext { getEntryState(block).merge(mergeNode, target.state); mergeNode.addForwardEnd(newEnd); - Debug.log("createTarget %s: merging state, result: %s", block, result); + debug.log("createTarget %s: merging state, result: %s", block, result); return result; } @@ -2416,10 +2636,10 @@ public class BytecodeParser implements GraphBuilderContext { // Ignore blocks that have no predecessors by the time their bytecodes are parsed FixedWithNextNode firstInstruction = getFirstInstruction(block); if (firstInstruction == null) { - Debug.log("Ignoring block %s", block); + debug.log("Ignoring block %s", block); return; } - try (Indent indent = Debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, firstInstruction, block.isLoopHeader)) { + try (Indent indent = debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, firstInstruction, block.isLoopHeader)) { lastInstr = firstInstruction; frameState = getEntryState(block); @@ -2430,10 +2650,8 @@ public class BytecodeParser implements GraphBuilderContext { setMergeStateAfter(block, firstInstruction); } - if (block == blockMap.getReturnBlock()) { - handleReturnBlock(); - } else if (block == blockMap.getUnwindBlock()) { - handleUnwindBlock(); + if (block == blockMap.getUnwindBlock()) { + handleUnwindBlock((ExceptionDispatchBlock) block); } else if (block instanceof ExceptionDispatchBlock) { createExceptionDispatch((ExceptionDispatchBlock) block); } else { @@ -2443,8 +2661,9 @@ public class BytecodeParser implements GraphBuilderContext { } } - private void handleUnwindBlock() { + private void handleUnwindBlock(ExceptionDispatchBlock block) { if (parent == null) { + finishPrepare(lastInstr, block.deoptBci); frameState.setRethrowException(false); createUnwind(); } else { @@ -2454,15 +2673,6 @@ public class BytecodeParser implements GraphBuilderContext { } } - private void handleReturnBlock() { - JavaKind returnKind = method.getSignature().getReturnKind().getStackKind(); - ValueNode x = returnKind == JavaKind.Void ? null : frameState.pop(returnKind); - assert frameState.stackSize() == 0; - beforeReturn(x, returnKind); - this.returnValue = x; - this.beforeReturnNode = this.lastInstr; - } - private void setMergeStateAfter(BciBlock block, FixedWithNextNode firstInstruction) { AbstractMergeNode abstractMergeNode = (AbstractMergeNode) firstInstruction; if (abstractMergeNode.stateAfter() == null) { @@ -2476,8 +2686,8 @@ public class BytecodeParser implements GraphBuilderContext { private void createUnwind() { assert frameState.stackSize() == 1 : frameState; - ValueNode exception = frameState.pop(JavaKind.Object); synchronizedEpilogue(BytecodeFrame.AFTER_EXCEPTION_BCI, null, null); + ValueNode exception = frameState.pop(JavaKind.Object); append(new UnwindNode(exception)); } @@ -2488,6 +2698,7 @@ public class BytecodeParser implements GraphBuilderContext { } genMonitorExit(methodSynchronizedObject, currentReturnValue, bci); assert !frameState.rethrowException(); + finishPrepare(lastInstr, bci); } if (frameState.lockDepth(false) != 0) { throw bailout("unbalanced monitors: too few exits exiting frame"); @@ -2574,7 +2785,7 @@ public class BytecodeParser implements GraphBuilderContext { */ setEntryState(block, frameState.copy()); - Debug.log(" created loop header %s", loopBegin); + debug.log(" created loop header %s", loopBegin); } else if (lastInstr instanceof MergeNode) { /* * All inputs of non-loop phi nodes are known by now. We can infer the stamp for the @@ -2583,7 +2794,7 @@ public class BytecodeParser implements GraphBuilderContext { frameState.inferPhiStamps((AbstractMergeNode) lastInstr); } assert lastInstr.next() == null : "instructions already appended at block " + block; - Debug.log(" frameState: %s", frameState); + debug.log(" frameState: %s", frameState); lastInstr = finishInstruction(lastInstr, frameState); @@ -2591,7 +2802,7 @@ public class BytecodeParser implements GraphBuilderContext { stream.setBCI(block.startBci); int bci = block.startBci; - BytecodesParsed.add(block.endBci - bci); + BytecodesParsed.add(debug, block.endBci - bci); /* Reset line number for new block */ if (graphBuilderConfig.insertFullInfopoints()) { @@ -2652,7 +2863,7 @@ public class BytecodeParser implements GraphBuilderContext { } private DebugCloseable openNodeContext() { - if (graphBuilderConfig.trackNodeSourcePosition() && !parsingIntrinsic()) { + if ((graphBuilderConfig.trackNodeSourcePosition() || debug.isDumpEnabledForMethod()) && !parsingIntrinsic()) { return graph.withNodeSourcePosition(createBytecodePosition()); } return null; @@ -2715,7 +2926,7 @@ public class BytecodeParser implements GraphBuilderContext { } private boolean traceState() { - if (Debug.isEnabled() && BytecodeParserOptions.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_STATE && Debug.isLogEnabled()) { + if (debug.isLogEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE) { frameState.traceState(); } return true; @@ -2727,12 +2938,6 @@ public class BytecodeParser implements GraphBuilderContext { BciBlock trueBlock = currentBlock.getSuccessor(0); BciBlock falseBlock = currentBlock.getSuccessor(1); - FrameState stateBefore = null; - ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin(); - if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { - stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null); - } - if (trueBlock == falseBlock) { // The target block is the same independent of the condition. appendGoto(trueBlock); @@ -2753,8 +2958,21 @@ public class BytecodeParser implements GraphBuilderContext { // Check whether the condition needs to negate the result. boolean negate = cond.canonicalNegate(); + genIf(condition, negate, trueBlock, falseBlock); + } + + protected void genIf(LogicNode conditionInput, boolean negateCondition, BciBlock trueBlockInput, BciBlock falseBlockInput) { + BciBlock trueBlock = trueBlockInput; + BciBlock falseBlock = falseBlockInput; + LogicNode condition = conditionInput; + FrameState stateBefore = null; + ProfilingPlugin profilingPlugin = this.graphBuilderConfig.getPlugins().getProfilingPlugin(); + if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) { + stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null); + } // Remove a logic negation node and fold it into the negate boolean. + boolean negate = negateCondition; if (condition instanceof LogicNegationNode) { LogicNegationNode logicNegationNode = (LogicNegationNode) condition; negate = !negate; @@ -2765,11 +2983,11 @@ public class BytecodeParser implements GraphBuilderContext { genConstantTargetIf(trueBlock, falseBlock, negate, condition); } else { if (condition.graph() == null) { - condition = graph.unique(condition); + condition = genUnique(condition); } // Need to get probability based on current bci. - double probability = branchProbability(); + double probability = branchProbability(condition); if (negate) { BciBlock tmpBlock = trueBlock; @@ -2815,13 +3033,6 @@ public class BytecodeParser implements GraphBuilderContext { ValueNode ifNode = genIfNode(condition, trueSuccessor, falseSuccessor, probability); postProcessIfNode(ifNode); append(ifNode); - if (parsingIntrinsic()) { - if (x instanceof BranchProbabilityNode) { - ((BranchProbabilityNode) x).simplify(null); - } else if (y instanceof BranchProbabilityNode) { - ((BranchProbabilityNode) y).simplify(null); - } - } } } @@ -2848,7 +3059,7 @@ public class BytecodeParser implements GraphBuilderContext { ConstantNode falseValue = graph.unique(ConstantNode.forInt(falseBlockInt)); ValueNode conditionalNode = ConditionalNode.create(condition, trueValue, falseValue); if (conditionalNode.graph() == null) { - conditionalNode = graph.addOrUnique(conditionalNode); + conditionalNode = graph.addOrUniqueWithInputs(conditionalNode); } if (genReturn) { JavaKind returnKind = method.getSignature().getReturnKind().getStackKind(); @@ -3039,6 +3250,19 @@ public class BytecodeParser implements GraphBuilderContext { frameState.push(kind, value); } + public void loadLocalObject(int index) { + ValueNode value = frameState.loadLocal(index, JavaKind.Object); + + int nextBCI = stream.nextBCI(); + int nextBC = stream.readUByte(nextBCI); + if (nextBCI <= currentBlock.endBci && nextBC == Bytecodes.GETFIELD) { + stream.next(); + genGetField(lookupField(stream.readCPI(), Bytecodes.GETFIELD), value); + } else { + frameState.push(JavaKind.Object, value); + } + } + public void storeLocal(JavaKind kind, int index) { ValueNode value = frameState.pop(kind); frameState.storeLocal(index, kind, value); @@ -3320,7 +3544,7 @@ public class BytecodeParser implements GraphBuilderContext { } private JavaTypeProfile getProfileForTypeCheck(TypeReference type) { - if (parsingIntrinsic() || profilingInfo == null || !optimisticOpts.useTypeCheckHints() || type.isExact()) { + if (parsingIntrinsic() || profilingInfo == null || !optimisticOpts.useTypeCheckHints(getOptions()) || type.isExact()) { return null; } else { return profilingInfo.getTypeProfile(bci()); @@ -3348,7 +3572,7 @@ public class BytecodeParser implements GraphBuilderContext { ValueNode castNode = null; if (profile != null) { if (profile.getNullSeen().isFalse()) { - object = appendNullCheck(object); + object = nullCheckedValue(object); ResolvedJavaType singleType = profile.asSingleType(); if (singleType != null && checkedType.getType().isAssignableFrom(singleType)) { LogicNode typeCheck = append(createInstanceOf(TypeReference.createExactTrusted(singleType), object, profile)); @@ -3356,36 +3580,25 @@ public class BytecodeParser implements GraphBuilderContext { castNode = object; } else { FixedGuardNode fixedGuard = append(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile, false)); - castNode = append(new PiNode(object, StampFactory.objectNonNull(TypeReference.createExactTrusted(singleType)), fixedGuard)); + castNode = append(PiNode.create(object, StampFactory.objectNonNull(TypeReference.createExactTrusted(singleType)), fixedGuard)); } } } } + + boolean nonNull = ((ObjectStamp) object.stamp()).nonNull(); if (castNode == null) { LogicNode condition = genUnique(createInstanceOfAllowNull(checkedType, object, null)); if (condition.isTautology()) { castNode = object; } else { FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, DeoptimizationReason.ClassCastException, DeoptimizationAction.InvalidateReprofile, false)); - castNode = append(new PiNode(object, StampFactory.object(checkedType), fixedGuard)); + castNode = append(PiNode.create(object, StampFactory.object(checkedType, nonNull), fixedGuard)); } } frameState.push(JavaKind.Object, castNode); } - private ValueNode appendNullCheck(ValueNode object) { - if (object.stamp() instanceof AbstractPointerStamp) { - AbstractPointerStamp stamp = (AbstractPointerStamp) object.stamp(); - if (stamp.nonNull()) { - return object; - } - } - - LogicNode isNull = append(IsNullNode.create(object)); - FixedGuardNode fixedGuard = append(new FixedGuardNode(isNull, DeoptimizationReason.NullCheckException, DeoptimizationAction.InvalidateReprofile, true)); - return append(new PiNode(object, object.stamp().join(StampFactory.objectNonNull()), fixedGuard)); - } - private void genInstanceOf() { int cpi = getStream().readCPI(); JavaType type = lookupType(cpi, INSTANCEOF); @@ -3407,7 +3620,7 @@ public class BytecodeParser implements GraphBuilderContext { LogicNode instanceOfNode = null; if (profile != null) { if (profile.getNullSeen().isFalse()) { - object = appendNullCheck(object); + object = nullCheckedValue(object); ResolvedJavaType singleType = profile.asSingleType(); if (singleType != null) { LogicNode typeCheck = append(createInstanceOf(TypeReference.createExactTrusted(singleType), object, profile)); @@ -3421,7 +3634,23 @@ public class BytecodeParser implements GraphBuilderContext { if (instanceOfNode == null) { instanceOfNode = createInstanceOf(resolvedType, object, null); } - frameState.push(JavaKind.Int, append(genConditional(genUnique(instanceOfNode)))); + LogicNode logicNode = genUnique(instanceOfNode); + + int next = getStream().nextBCI(); + int value = getStream().readUByte(next); + if (next <= currentBlock.endBci && (value == Bytecodes.IFEQ || value == Bytecodes.IFNE)) { + getStream().next(); + BciBlock firstSucc = currentBlock.getSuccessor(0); + BciBlock secondSucc = currentBlock.getSuccessor(1); + if (firstSucc != secondSucc) { + genIf(instanceOfNode, value != Bytecodes.IFNE, firstSucc, secondSucc); + } else { + appendGoto(firstSucc); + } + } else { + // Most frequent for value is IRETURN, followed by ISTORE. + frameState.push(JavaKind.Int, append(genConditional(logicNode))); + } } void genNewInstance(int cpi) { @@ -3543,9 +3772,9 @@ public class BytecodeParser implements GraphBuilderContext { ResolvedJavaType resolvedType = (ResolvedJavaType) type; ClassInitializationPlugin classInitializationPlugin = this.graphBuilderConfig.getPlugins().getClassInitializationPlugin(); - if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType.getArrayClass())) { + if (classInitializationPlugin != null && classInitializationPlugin.shouldApply(this, resolvedType)) { FrameState stateBefore = frameState.create(bci(), getNonIntrinsicAncestor(), false, null, null); - classInitializationPlugin.apply(this, resolvedType.getArrayClass(), stateBefore); + classInitializationPlugin.apply(this, resolvedType, stateBefore); } for (int i = rank - 1; i >= 0; i--) { @@ -3562,15 +3791,21 @@ public class BytecodeParser implements GraphBuilderContext { } private void genGetField(JavaField field) { - ValueNode receiver = emitExplicitExceptions(frameState.pop(JavaKind.Object), null); + genGetField(field, frameState.pop(JavaKind.Object)); + } - if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { + private void genGetField(JavaField field, ValueNode receiverInput) { + ValueNode receiver = emitExplicitExceptions(receiverInput); + if (field instanceof ResolvedJavaField) { + ResolvedJavaField resolvedField = (ResolvedJavaField) field; + genGetField(resolvedField, receiver); + } else { handleUnresolvedLoadField(field, receiver); - return; } - ResolvedJavaField resolvedField = (ResolvedJavaField) field; + } - if (!parsingIntrinsic() && GeneratePIC.getValue()) { + private void genGetField(ResolvedJavaField resolvedField, ValueNode receiver) { + if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { graph.recordField(resolvedField); } @@ -3580,72 +3815,93 @@ public class BytecodeParser implements GraphBuilderContext { } } - frameState.push(field.getJavaKind(), append(genLoadField(receiver, resolvedField))); - if (resolvedField.getName().equals("referent") && resolvedField.getDeclaringClass().equals(metaAccess.lookupJavaType(Reference.class))) { + ValueNode fieldRead = append(genLoadField(receiver, resolvedField)); + + if (resolvedField.getDeclaringClass().getName().equals("Ljava/lang/ref/Reference;") && resolvedField.getName().equals("referent")) { LocationIdentity referentIdentity = new FieldLocationIdentity(resolvedField); append(new MembarNode(0, referentIdentity)); } + + JavaKind fieldKind = resolvedField.getJavaKind(); + + if (resolvedField.isVolatile() && fieldRead instanceof LoadFieldNode) { + StateSplitProxyNode readProxy = append(genVolatileFieldReadProxy(fieldRead)); + frameState.push(fieldKind, readProxy); + readProxy.setStateAfter(frameState.create(stream.nextBCI(), readProxy)); + } else { + frameState.push(fieldKind, fieldRead); + } } /** * @param receiver the receiver of an object based operation * @param index the index of an array based operation that is to be tested for out of bounds. * This is null for a non-array operation. - * @return the receiver value possibly modified to have a tighter stamp + * @return the receiver value possibly modified to have a non-null stamp */ protected ValueNode emitExplicitExceptions(ValueNode receiver, ValueNode index) { - assert receiver != null; - if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.OmitAll) { - return receiver; - } - if (graphBuilderConfig.getBytecodeExceptionMode() == BytecodeExceptionMode.Profile && (profilingInfo == null || - (optimisticOpts.useExceptionProbabilityForOperations() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE && !GraalOptions.StressExplicitExceptionCode.getValue()))) { - return receiver; - } - - ValueNode nonNullReceiver = emitExplicitNullCheck(receiver); - if (index != null) { + if (needsExplicitException()) { + ValueNode nonNullReceiver = emitExplicitNullCheck(receiver); ValueNode length = append(genArrayLength(nonNullReceiver)); emitExplicitBoundsCheck(index, length); + return nonNullReceiver; } - EXPLICIT_EXCEPTIONS.increment(); - return nonNullReceiver; + return receiver; + } + + protected ValueNode emitExplicitExceptions(ValueNode receiver) { + if (StampTool.isPointerNonNull(receiver) || !needsExplicitException()) { + return receiver; + } else { + return emitExplicitNullCheck(receiver); + } + } + + private boolean needsExplicitException() { + BytecodeExceptionMode exceptionMode = graphBuilderConfig.getBytecodeExceptionMode(); + if (exceptionMode == BytecodeExceptionMode.CheckAll || StressExplicitExceptionCode.getValue(options)) { + return true; + } else if (exceptionMode == BytecodeExceptionMode.Profile && profilingInfo != null) { + return profilingInfo.getExceptionSeen(bci()) == TriState.TRUE; + } + return false; } private void genPutField(JavaField field) { - ValueNode value = frameState.pop(field.getJavaKind()); - ValueNode receiver = emitExplicitExceptions(frameState.pop(JavaKind.Object), null); + genPutField(field, frameState.pop(field.getJavaKind())); + } - if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaField) field).getDeclaringClass().isInitialized()) { - handleUnresolvedStoreField(field, value, receiver); - return; - } - ResolvedJavaField resolvedField = (ResolvedJavaField) field; + private void genPutField(JavaField field, ValueNode value) { + ValueNode receiver = emitExplicitExceptions(frameState.pop(JavaKind.Object)); + if (field instanceof ResolvedJavaField) { + ResolvedJavaField resolvedField = (ResolvedJavaField) field; - if (!parsingIntrinsic() && GeneratePIC.getValue()) { - graph.recordField(resolvedField); - } - - for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) { - if (plugin.handleStoreField(this, receiver, resolvedField, value)) { - return; + if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { + graph.recordField(resolvedField); } - } - if (resolvedField.isFinal() && method.isConstructor()) { - finalBarrierRequired = true; + for (NodePlugin plugin : graphBuilderConfig.getPlugins().getNodePlugins()) { + if (plugin.handleStoreField(this, receiver, resolvedField, value)) { + return; + } + } + + if (resolvedField.isFinal() && method.isConstructor()) { + finalBarrierRequired = true; + } + genStoreField(receiver, resolvedField, value); + } else { + handleUnresolvedStoreField(field, value, receiver); } - genStoreField(receiver, resolvedField, value); } private void genGetStatic(JavaField field) { - if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { - handleUnresolvedLoadField(field, null); + ResolvedJavaField resolvedField = resolveStaticFieldAccess(field, null); + if (resolvedField == null) { return; } - ResolvedJavaField resolvedField = (ResolvedJavaField) field; - if (!parsingIntrinsic() && GeneratePIC.getValue()) { + if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { graph.recordField(resolvedField); } @@ -3673,15 +3929,41 @@ public class BytecodeParser implements GraphBuilderContext { frameState.push(field.getJavaKind(), append(genLoadField(null, resolvedField))); } + private ResolvedJavaField resolveStaticFieldAccess(JavaField field, ValueNode value) { + if (field instanceof ResolvedJavaField) { + ResolvedJavaField resolvedField = (ResolvedJavaField) field; + if (resolvedField.getDeclaringClass().isInitialized()) { + return resolvedField; + } + /* + * Static fields have initialization semantics but may be safely accessed under certain + * conditions while the class is being initialized. Executing in the clinit or init of + * classes which are subtypes of the field holder are sure to be running in a context + * where the access is safe. + */ + if (resolvedField.getDeclaringClass().isAssignableFrom(method.getDeclaringClass())) { + if (method.isClassInitializer() || method.isConstructor()) { + return resolvedField; + } + } + } + if (value == null) { + handleUnresolvedLoadField(field, null); + } else { + handleUnresolvedStoreField(field, value, null); + + } + return null; + } + private void genPutStatic(JavaField field) { ValueNode value = frameState.pop(field.getJavaKind()); - if (!(field instanceof ResolvedJavaField) || !((ResolvedJavaType) field.getDeclaringClass()).isInitialized()) { - handleUnresolvedStoreField(field, value, null); + ResolvedJavaField resolvedField = resolveStaticFieldAccess(field, value); + if (resolvedField == null) { return; } - ResolvedJavaField resolvedField = (ResolvedJavaField) field; - if (!parsingIntrinsic() && GeneratePIC.getValue()) { + if (!parsingIntrinsic() && GeneratePIC.getValue(getOptions())) { graph.recordField(resolvedField); } @@ -3705,7 +3987,7 @@ public class BytecodeParser implements GraphBuilderContext { if (prob != null) { assert prob.length == numberOfCases; } else { - Debug.log("Missing probability (switch) in %s at bci %d", method, bci); + debug.log("Missing probability (switch) in %s at bci %d", method, bci); prob = new double[numberOfCases]; for (int i = 0; i < numberOfCases; i++) { prob[i] = 1.0d / numberOfCases; @@ -3741,12 +4023,10 @@ public class BytecodeParser implements GraphBuilderContext { int nofCases = bs.numberOfCases(); double[] keyProbabilities = switchProbability(nofCases + 1, bci); - Map bciToBlockSuccessorIndex = new HashMap<>(); + EconomicMap bciToBlockSuccessorIndex = EconomicMap.create(Equivalence.DEFAULT); for (int i = 0; i < currentBlock.getSuccessorCount(); i++) { assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci); - if (!bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci)) { - bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i)); - } + bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i)); } ArrayList actualSuccessors = new ArrayList<>(); @@ -3782,22 +4062,46 @@ public class BytecodeParser implements GraphBuilderContext { } protected boolean isNeverExecutedCode(double probability) { - return probability == 0 && optimisticOpts.removeNeverExecutedCode(); + return probability == 0 && optimisticOpts.removeNeverExecutedCode(getOptions()); } - protected double branchProbability() { + private double rawBranchProbability(LogicNode conditionInput) { + if (conditionInput instanceof IntegerEqualsNode) { + // Propagate injected branch probability if any. + IntegerEqualsNode condition = (IntegerEqualsNode) conditionInput; + BranchProbabilityNode injectedProbability = null; + ValueNode other = null; + if (condition.getX() instanceof BranchProbabilityNode) { + injectedProbability = (BranchProbabilityNode) condition.getX(); + other = condition.getY(); + } else if (condition.getY() instanceof BranchProbabilityNode) { + injectedProbability = (BranchProbabilityNode) condition.getY(); + other = condition.getX(); + } + + if (injectedProbability != null && injectedProbability.getProbability().isConstant() && other != null && other.isConstant()) { + double probabilityValue = injectedProbability.getProbability().asJavaConstant().asDouble(); + return other.asJavaConstant().asInt() == 0 ? 1.0 - probabilityValue : probabilityValue; + } + } + if (profilingInfo == null) { return 0.5; } assert assertAtIfBytecode(); - double probability = profilingInfo.getBranchTakenProbability(bci()); + + return profilingInfo.getBranchTakenProbability(bci()); + } + + protected double branchProbability(LogicNode conditionInput) { + double probability = rawBranchProbability(conditionInput); if (probability < 0) { assert probability == -1 : "invalid probability"; - Debug.log("missing probability in %s at bci %d", code, bci()); + debug.log("missing probability in %s at bci %d", code, bci()); probability = 0.5; } - if (!optimisticOpts.removeNeverExecutedCode()) { + if (!optimisticOpts.removeNeverExecutedCode(getOptions())) { if (probability == 0) { probability = 0.0000001; } else if (probability == 1) { @@ -3863,7 +4167,7 @@ public class BytecodeParser implements GraphBuilderContext { case LLOAD : loadLocal(stream.readLocalIndex(), JavaKind.Long); break; case FLOAD : loadLocal(stream.readLocalIndex(), JavaKind.Float); break; case DLOAD : loadLocal(stream.readLocalIndex(), JavaKind.Double); break; - case ALOAD : loadLocal(stream.readLocalIndex(), JavaKind.Object); break; + case ALOAD : loadLocalObject(stream.readLocalIndex()); break; case ILOAD_0 : // fall through case ILOAD_1 : // fall through case ILOAD_2 : // fall through @@ -3883,7 +4187,7 @@ public class BytecodeParser implements GraphBuilderContext { case ALOAD_0 : // fall through case ALOAD_1 : // fall through case ALOAD_2 : // fall through - case ALOAD_3 : loadLocal(opcode - ALOAD_0, JavaKind.Object); break; + case ALOAD_3 : loadLocalObject(opcode - ALOAD_0); break; case IALOAD : genLoadIndexed(JavaKind.Int ); break; case LALOAD : genLoadIndexed(JavaKind.Long ); break; case FALOAD : genLoadIndexed(JavaKind.Float ); break; @@ -4047,7 +4351,7 @@ public class BytecodeParser implements GraphBuilderContext { } private void genArrayLength() { - ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object), null); + ValueNode array = emitExplicitExceptions(frameState.pop(JavaKind.Object)); frameState.push(JavaKind.Int, append(genArrayLength(array))); } @@ -4066,7 +4370,7 @@ public class BytecodeParser implements GraphBuilderContext { } protected boolean traceInstruction(int bci, int opcode, boolean blockStart) { - if (Debug.isEnabled() && BytecodeParserOptions.TraceBytecodeParserLevel.getValue() >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) { + if (debug.isLogEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS) { traceInstructionHelper(bci, opcode, blockStart); } return true; @@ -4087,7 +4391,7 @@ public class BytecodeParser implements GraphBuilderContext { if (!currentBlock.getJsrScope().isEmpty()) { sb.append(' ').append(currentBlock.getJsrScope()); } - Debug.log("%s", sb); + debug.log("%s", sb); } @Override @@ -4107,11 +4411,4 @@ public class BytecodeParser implements GraphBuilderContext { static String nSpaces(int n) { return n == 0 ? "" : format("%" + n + "s", ""); } - - @SuppressWarnings("all") - private static boolean assertionsEnabled() { - boolean assertionsEnabled = false; - assert assertionsEnabled = true; - return assertionsEnabled; - } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java index 9328c7614b0..d8c8f878b71 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java @@ -24,8 +24,7 @@ package org.graalvm.compiler.java; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.StableOptionValue; +import org.graalvm.compiler.options.OptionKey; /** * Options related to {@link BytecodeParser}. @@ -36,30 +35,33 @@ import org.graalvm.compiler.options.StableOptionValue; public class BytecodeParserOptions { // @formatter:off @Option(help = "The trace level for the bytecode parser used when building a graph from bytecode", type = OptionType.Debug) - public static final OptionValue TraceBytecodeParserLevel = new OptionValue<>(0); + public static final OptionKey TraceBytecodeParserLevel = new OptionKey<>(0); @Option(help = "Inlines trivial methods during bytecode parsing.", type = OptionType.Expert) - public static final StableOptionValue InlineDuringParsing = new StableOptionValue<>(true); + public static final OptionKey InlineDuringParsing = new OptionKey<>(true); + + @Option(help = "Inlines partial intrinsic exits during bytecode parsing when possible. " + + "A partial intrinsic exit is a call within an intrinsic to the method " + + "being intrinsified and denotes semantics of the original method that " + + "the intrinsic does not support.", type = OptionType.Expert) + public static final OptionKey InlinePartialIntrinsicExitDuringParsing = new OptionKey<>(true); @Option(help = "Inlines intrinsic methods during bytecode parsing.", type = OptionType.Expert) - public static final StableOptionValue InlineIntrinsicsDuringParsing = new StableOptionValue<>(true); + public static final OptionKey InlineIntrinsicsDuringParsing = new OptionKey<>(true); @Option(help = "Traces inlining performed during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue TraceInlineDuringParsing = new StableOptionValue<>(false); + public static final OptionKey TraceInlineDuringParsing = new OptionKey<>(false); @Option(help = "Traces use of plugins during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue TraceParserPlugins = new StableOptionValue<>(false); + public static final OptionKey TraceParserPlugins = new OptionKey<>(false); @Option(help = "Maximum depth when inlining during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue InlineDuringParsingMaxDepth = new StableOptionValue<>(10); - - @Option(help = "Dump graphs after non-trivial changes during bytecode parsing.", type = OptionType.Debug) - public static final StableOptionValue DumpDuringGraphBuilding = new StableOptionValue<>(false); + public static final OptionKey InlineDuringParsingMaxDepth = new OptionKey<>(10); @Option(help = "When creating info points hide the methods of the substitutions.", type = OptionType.Debug) - public static final OptionValue HideSubstitutionStates = new OptionValue<>(false); + public static final OptionKey HideSubstitutionStates = new OptionKey<>(false); @Option(help = "Use intrinsics guarded by a virtual dispatch test at indirect call sites.", type = OptionType.Debug) - public static final OptionValue UseGuardedIntrinsics = new OptionValue<>(true); + public static final OptionKey UseGuardedIntrinsics = new OptionKey<>(true); // @formatter:on } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java index c2cc0ae369f..94bcf84ea10 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java @@ -23,8 +23,6 @@ package org.graalvm.compiler.java; import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; import org.graalvm.compiler.nodes.AbstractBeginNode; import org.graalvm.compiler.nodes.AbstractMergeNode; @@ -36,6 +34,7 @@ import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.graph.ReentrantNodeIterator; +import org.graalvm.util.EconomicMap; public final class ComputeLoopFrequenciesClosure extends ReentrantNodeIterator.NodeIteratorClosure { @@ -54,7 +53,11 @@ public final class ComputeLoopFrequenciesClosure extends ReentrantNodeIterator.N @Override protected Double merge(AbstractMergeNode merge, List states) { // a merge has the sum of all predecessor probabilities - return states.stream().collect(Collectors.summingDouble(d -> d)); + double result = 0.0; + for (double d : states) { + result += d; + } + return result; } @Override @@ -65,10 +68,13 @@ public final class ComputeLoopFrequenciesClosure extends ReentrantNodeIterator.N } @Override - protected Map processLoop(LoopBeginNode loop, Double initialState) { - Map exitStates = ReentrantNodeIterator.processLoop(this, loop, 1D).exitStates; + protected EconomicMap processLoop(LoopBeginNode loop, Double initialState) { + EconomicMap exitStates = ReentrantNodeIterator.processLoop(this, loop, 1D).exitStates; - double exitProbability = exitStates.values().stream().mapToDouble(d -> d).sum(); + double exitProbability = 0.0; + for (double d : exitStates.getValues()) { + exitProbability += d; + } exitProbability = Math.min(1D, exitProbability); if (exitProbability < ControlFlowGraph.MIN_PROBABILITY) { exitProbability = ControlFlowGraph.MIN_PROBABILITY; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesProvider.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesCreator.java similarity index 81% rename from hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesProvider.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesCreator.java index 8be604a4a87..b123ed6ea85 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesProvider.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesCreator.java @@ -25,24 +25,25 @@ package org.graalvm.compiler.java; import org.graalvm.compiler.lir.phases.LIRSuites; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.CompilerConfiguration; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.Suites; -public class DefaultSuitesProvider extends SuitesProviderBase { +public class DefaultSuitesCreator extends SuitesProviderBase { private final CompilerConfiguration compilerConfiguration; - public DefaultSuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) { + public DefaultSuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) { super(); this.defaultGraphBuilderSuite = createGraphBuilderSuite(plugins); this.compilerConfiguration = compilerConfiguration; } @Override - public Suites createSuites() { - return Suites.createSuites(compilerConfiguration); + public Suites createSuites(OptionValues options) { + return Suites.createSuites(compilerConfiguration, options); } protected PhaseSuite createGraphBuilderSuite(Plugins plugins) { @@ -52,7 +53,7 @@ public class DefaultSuitesProvider extends SuitesProviderBase { } @Override - public LIRSuites createLIRSuites() { - return Suites.createLIRSuites(compilerConfiguration); + public LIRSuites createLIRSuites(OptionValues options) { + return Suites.createLIRSuites(compilerConfiguration, options); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java index 092d213d903..f045d25a6bd 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java @@ -42,10 +42,11 @@ import java.util.function.Function; import org.graalvm.compiler.bytecode.Bytecode; import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.core.common.PermanentBailoutException; import org.graalvm.compiler.core.common.type.StampFactory; import org.graalvm.compiler.core.common.type.StampPair; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.java.BciBlockMapping.BciBlock; import org.graalvm.compiler.nodeinfo.Verbosity; @@ -99,7 +100,9 @@ public final class FrameStateBuilder implements SideEffectsState { private MonitorIdNode[] monitorIds; private final StructuredGraph graph; + private final boolean clearNonLiveLocals; private FrameState outerFrameState; + private NodeSourcePosition outerSourcePosition; /** * The closest {@link StateSplit#hasSideEffect() side-effect} predecessors. There will be more @@ -142,6 +145,7 @@ public final class FrameStateBuilder implements SideEffectsState { this.monitorIds = EMPTY_MONITOR_ARRAY; this.graph = graph; + this.clearNonLiveLocals = GraalOptions.OptClearNonLiveLocals.getValue(graph.getOptions()); this.canVerifyKind = true; } @@ -263,6 +267,7 @@ public final class FrameStateBuilder implements SideEffectsState { assert other.graph != null; graph = other.graph; + clearNonLiveLocals = other.clearNonLiveLocals; monitorIds = other.monitorIds.length == 0 ? other.monitorIds : other.monitorIds.clone(); assert locals.length == code.getMaxLocals(); @@ -303,7 +308,8 @@ public final class FrameStateBuilder implements SideEffectsState { public FrameState create(int bci, StateSplit forStateSplit) { if (parser != null && parser.parsingIntrinsic()) { - return parser.intrinsicContext.createFrameState(parser.getGraph(), this, forStateSplit); + NodeSourcePosition sourcePosition = createBytecodePosition(bci, false); + return parser.intrinsicContext.createFrameState(parser.getGraph(), this, forStateSplit, sourcePosition); } // Skip intrinsic frames @@ -346,8 +352,12 @@ public final class FrameStateBuilder implements SideEffectsState { } public NodeSourcePosition createBytecodePosition(int bci) { + return createBytecodePosition(bci, HideSubstitutionStates.getValue(parser.graph.getOptions())); + } + + private NodeSourcePosition createBytecodePosition(int bci, boolean hideSubstitutionStates) { BytecodeParser parent = parser.getParent(); - if (HideSubstitutionStates.getValue()) { + if (hideSubstitutionStates) { if (parser.parsingIntrinsic()) { // Attribute to the method being replaced return new NodeSourcePosition(constantReceiver, parent.getFrameStateBuilder().createBytecodePosition(parent.bci()), parser.intrinsicContext.getOriginalMethod(), -1); @@ -355,13 +365,12 @@ public final class FrameStateBuilder implements SideEffectsState { // Skip intrinsic frames parent = parser.getNonIntrinsicAncestor(); } - return create(null, constantReceiver, bci, parent); + return create(constantReceiver, bci, parent, hideSubstitutionStates); } - private NodeSourcePosition create(NodeSourcePosition o, JavaConstant receiver, int bci, BytecodeParser parent) { - NodeSourcePosition outer = o; - if (outer == null && parent != null) { - outer = parent.getFrameStateBuilder().createBytecodePosition(parent.bci()); + private NodeSourcePosition create(JavaConstant receiver, int bci, BytecodeParser parent, boolean hideSubstitutionStates) { + if (outerSourcePosition == null && parent != null) { + outerSourcePosition = parent.getFrameStateBuilder().createBytecodePosition(parent.bci(), hideSubstitutionStates); } if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI && parent != null) { return FrameState.toSourcePosition(outerFrameState); @@ -369,7 +378,7 @@ public final class FrameStateBuilder implements SideEffectsState { if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) { throw shouldNotReachHere(); } - return new NodeSourcePosition(receiver, outer, code.getMethod(), bci); + return new NodeSourcePosition(receiver, outerSourcePosition, code.getMethod(), bci); } public FrameStateBuilder copy() { @@ -494,48 +503,50 @@ public final class FrameStateBuilder implements SideEffectsState { } public void insertLoopProxies(LoopExitNode loopExit, FrameStateBuilder loopEntryState) { + DebugContext debug = graph.getDebug(); for (int i = 0; i < localsSize(); i++) { ValueNode value = locals[i]; if (value != null && value != TWO_SLOT_MARKER && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { - Debug.log(" inserting proxy for %s", value); + debug.log(" inserting proxy for %s", value); locals[i] = ProxyNode.forValue(value, loopExit, graph); } } for (int i = 0; i < stackSize(); i++) { ValueNode value = stack[i]; if (value != null && value != TWO_SLOT_MARKER && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { - Debug.log(" inserting proxy for %s", value); + debug.log(" inserting proxy for %s", value); stack[i] = ProxyNode.forValue(value, loopExit, graph); } } for (int i = 0; i < lockedObjects.length; i++) { ValueNode value = lockedObjects[i]; if (value != null && (!loopEntryState.contains(value) || loopExit.loopBegin().isPhiAtMerge(value))) { - Debug.log(" inserting proxy for %s", value); + debug.log(" inserting proxy for %s", value); lockedObjects[i] = ProxyNode.forValue(value, loopExit, graph); } } } public void insertProxies(Function proxyFunction) { + DebugContext debug = graph.getDebug(); for (int i = 0; i < localsSize(); i++) { ValueNode value = locals[i]; if (value != null && value != TWO_SLOT_MARKER) { - Debug.log(" inserting proxy for %s", value); + debug.log(" inserting proxy for %s", value); locals[i] = proxyFunction.apply(value); } } for (int i = 0; i < stackSize(); i++) { ValueNode value = stack[i]; if (value != null && value != TWO_SLOT_MARKER) { - Debug.log(" inserting proxy for %s", value); + debug.log(" inserting proxy for %s", value); stack[i] = proxyFunction.apply(value); } } for (int i = 0; i < lockedObjects.length; i++) { ValueNode value = lockedObjects[i]; if (value != null) { - Debug.log(" inserting proxy for %s", value); + debug.log(" inserting proxy for %s", value); lockedObjects[i] = proxyFunction.apply(value); } } @@ -624,7 +635,7 @@ public final class FrameStateBuilder implements SideEffectsState { * slots at the OSR entry aren't cleared. it is also not enough to rely on PiNodes with * Kind.Illegal, because the conflicting branch might not have been parsed. */ - if (!parser.graphBuilderConfig.clearNonLiveLocals()) { + if (!clearNonLiveLocals) { return; } if (liveIn) { @@ -987,14 +998,15 @@ public final class FrameStateBuilder implements SideEffectsState { } public void traceState() { - Debug.log("| state [nr locals = %d, stack depth = %d, method = %s]", localsSize(), stackSize(), getMethod()); + DebugContext debug = graph.getDebug(); + debug.log("| state [nr locals = %d, stack depth = %d, method = %s]", localsSize(), stackSize(), getMethod()); for (int i = 0; i < localsSize(); ++i) { ValueNode value = locals[i]; - Debug.log("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value); + debug.log("| local[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value); } for (int i = 0; i < stackSize(); ++i) { ValueNode value = stack[i]; - Debug.log("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value); + debug.log("| stack[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value); } } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/JsrNotSupportedBailout.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/JsrNotSupportedBailout.java index 8baadb649e9..47e4b9333ab 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/JsrNotSupportedBailout.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/JsrNotSupportedBailout.java @@ -22,7 +22,7 @@ */ package org.graalvm.compiler.java; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; public class JsrNotSupportedBailout extends PermanentBailoutException { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/LocalLiveness.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/LocalLiveness.java index 73b9f1d2c83..dacfbf03e93 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/LocalLiveness.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/LocalLiveness.java @@ -76,7 +76,7 @@ import static org.graalvm.compiler.bytecode.Bytecodes.LSTORE_3; import static org.graalvm.compiler.bytecode.Bytecodes.RET; import org.graalvm.compiler.bytecode.BytecodeStream; -import org.graalvm.compiler.debug.Debug; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.java.BciBlockMapping.BciBlock; /** @@ -86,9 +86,9 @@ import org.graalvm.compiler.java.BciBlockMapping.BciBlock; public abstract class LocalLiveness { protected final BciBlock[] blocks; - public static LocalLiveness compute(BytecodeStream stream, BciBlock[] blocks, int maxLocals, int loopCount) { + public static LocalLiveness compute(DebugContext debug, BytecodeStream stream, BciBlock[] blocks, int maxLocals, int loopCount) { LocalLiveness liveness = maxLocals <= 64 ? new SmallLocalLiveness(blocks, maxLocals, loopCount) : new LargeLocalLiveness(blocks, maxLocals, loopCount); - liveness.computeLiveness(stream); + liveness.computeLiveness(debug, stream); return liveness; } @@ -96,7 +96,7 @@ public abstract class LocalLiveness { this.blocks = blocks; } - void computeLiveness(BytecodeStream stream) { + void computeLiveness(DebugContext debug, BytecodeStream stream) { for (BciBlock block : blocks) { computeLocalLiveness(stream, block); } @@ -104,18 +104,18 @@ public abstract class LocalLiveness { boolean changed; int iteration = 0; do { - assert traceIteration(iteration); + assert traceIteration(debug, iteration); changed = false; for (int i = blocks.length - 1; i >= 0; i--) { BciBlock block = blocks[i]; int blockID = block.getId(); - assert traceStart(block, blockID); + assert traceStart(debug, block, blockID); boolean blockChanged = (iteration == 0); if (block.getSuccessorCount() > 0) { int oldCardinality = liveOutCardinality(blockID); for (BciBlock sux : block.getSuccessors()) { - assert traceSuccessor(sux); + assert traceSuccessor(debug, sux); propagateLiveness(blockID, sux.getId()); } blockChanged |= (oldCardinality != liveOutCardinality(blockID)); @@ -123,7 +123,7 @@ public abstract class LocalLiveness { if (blockChanged) { updateLiveness(blockID); - assert traceEnd(block, blockID); + assert traceEnd(debug, block, blockID); } changed |= blockChanged; } @@ -131,29 +131,29 @@ public abstract class LocalLiveness { } while (changed); } - private static boolean traceIteration(int iteration) { - Debug.log("Iteration %d", iteration); + private static boolean traceIteration(DebugContext debug, int iteration) { + debug.log("Iteration %d", iteration); return true; } - private boolean traceEnd(BciBlock block, int blockID) { - if (Debug.isLogEnabled()) { - Debug.logv(" end B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), + private boolean traceEnd(DebugContext debug, BciBlock block, int blockID) { + if (debug.isLogEnabled()) { + debug.logv(" end B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), debugLiveKill(blockID)); } return true; } - private boolean traceSuccessor(BciBlock sux) { - if (Debug.isLogEnabled()) { - Debug.log(" Successor B%d: %s", sux.getId(), debugLiveIn(sux.getId())); + private boolean traceSuccessor(DebugContext debug, BciBlock sux) { + if (debug.isLogEnabled()) { + debug.log(" Successor B%d: %s", sux.getId(), debugLiveIn(sux.getId())); } return true; } - private boolean traceStart(BciBlock block, int blockID) { - if (Debug.isLogEnabled()) { - Debug.logv(" start B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), + private boolean traceStart(DebugContext debug, BciBlock block, int blockID) { + if (debug.isLogEnabled()) { + debug.logv(" start B%d [%d, %d] in: %s out: %s gen: %s kill: %s", block.getId(), block.startBci, block.endBci, debugLiveIn(blockID), debugLiveOut(blockID), debugLiveGen(blockID), debugLiveKill(blockID)); } return true; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/SuitesProviderBase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/SuitesProviderBase.java index 025fe1f16c4..2244df3c80b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/SuitesProviderBase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/SuitesProviderBase.java @@ -23,8 +23,7 @@ package org.graalvm.compiler.java; import org.graalvm.compiler.lir.phases.LIRSuites; -import org.graalvm.compiler.options.DerivedOptionValue; -import org.graalvm.compiler.options.DerivedOptionValue.OptionSupplier; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.tiers.HighTierContext; import org.graalvm.compiler.phases.tiers.Suites; @@ -32,44 +31,11 @@ import org.graalvm.compiler.phases.tiers.SuitesCreator; public abstract class SuitesProviderBase implements SuitesCreator { - protected final DerivedOptionValue defaultSuites; protected PhaseSuite defaultGraphBuilderSuite; - protected final DerivedOptionValue defaultLIRSuites; - - private class SuitesSupplier implements OptionSupplier { - - private static final long serialVersionUID = 2677805381215454728L; - - @Override - public Suites get() { - Suites suites = createSuites(); - suites.setImmutable(); - return suites; - } - - } - - private class LIRSuitesSupplier implements OptionSupplier { - - private static final long serialVersionUID = 312070237227476252L; - - @Override - public LIRSuites get() { - LIRSuites lirSuites = createLIRSuites(); - lirSuites.setImmutable(); - return lirSuites; - } - - } - - public SuitesProviderBase() { - this.defaultSuites = new DerivedOptionValue<>(new SuitesSupplier()); - this.defaultLIRSuites = new DerivedOptionValue<>(new LIRSuitesSupplier()); - } @Override - public final Suites getDefaultSuites() { - return defaultSuites.getValue(); + public final Suites getDefaultSuites(OptionValues options) { + return createSuites(options); } @Override @@ -78,13 +44,13 @@ public abstract class SuitesProviderBase implements SuitesCreator { } @Override - public final LIRSuites getDefaultLIRSuites() { - return defaultLIRSuites.getValue(); + public final LIRSuites getDefaultLIRSuites(OptionValues options) { + return createLIRSuites(options); } @Override - public abstract LIRSuites createLIRSuites(); + public abstract LIRSuites createLIRSuites(OptionValues options); @Override - public abstract Suites createSuites(); + public abstract Suites createSuites(OptionValues options); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java index d240feec5ca..f9c1c35d7c9 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/JTTTest.java @@ -27,21 +27,22 @@ import static java.lang.reflect.Modifier.isStatic; import java.util.Collections; import java.util.Set; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.ParameterNode; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.Builder; +import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.phases.PhaseSuite; +import org.graalvm.compiler.phases.tiers.HighTierContext; +import org.junit.Assert; + import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.ResolvedJavaMethod; -import org.junit.Assert; - -import org.graalvm.compiler.core.common.CompilationIdentifier; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.nodes.ConstantNode; -import org.graalvm.compiler.nodes.ParameterNode; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; - /** * Base class for the JTT tests. *

      @@ -65,9 +66,10 @@ public class JTTTest extends GraalCompilerTest { } @Override - protected StructuredGraph parseEager(ResolvedJavaMethod m, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { - StructuredGraph graph = super.parseEager(m, allowAssumptions, compilationId); + protected StructuredGraph parse(Builder builder, PhaseSuite graphBuilderSuite) { + StructuredGraph graph = super.parse(builder, graphBuilderSuite); if (argsToBind != null) { + ResolvedJavaMethod m = graph.method(); Object receiver = isStatic(m.getModifiers()) ? null : this; Object[] args = argsWithReceiver(receiver, argsToBind); JavaType[] parameterTypes = m.toParameterTypes(); @@ -82,8 +84,8 @@ public class JTTTest extends GraalCompilerTest { } @Override - protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) { - return super.getCode(method, graph, argsToBind != null); + protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { + return super.getCode(method, graph, argsToBind != null, installAsDefault, options); } Double delta; @@ -104,14 +106,18 @@ public class JTTTest extends GraalCompilerTest { } protected void runTest(String name, Object... args) { - runTest(EMPTY, name, args); + runTest(getInitialOptions(), name, args); + } + + protected void runTest(OptionValues options, String name, Object... args) { + runTest(options, EMPTY, true, false, name, args); } protected void runTest(Set shouldNotDeopt, String name, Object... args) { - runTest(shouldNotDeopt, true, false, name, args); + runTest(getInitialOptions(), shouldNotDeopt, true, false, name, args); } - protected void runTest(Set shouldNotDeopt, boolean bind, boolean noProfile, String name, Object... args) { + protected void runTest(OptionValues options, Set shouldNotDeopt, boolean bind, boolean noProfile, String name, Object... args) { ResolvedJavaMethod method = getResolvedJavaMethod(name); Object receiver = method.isStatic() ? null : this; @@ -121,14 +127,14 @@ public class JTTTest extends GraalCompilerTest { method.reprofile(); } - testAgainstExpected(method, expect, shouldNotDeopt, receiver, args); + testAgainstExpected(options, method, expect, shouldNotDeopt, receiver, args); if (args.length > 0 && bind) { if (noProfile) { method.reprofile(); } this.argsToBind = args; - testAgainstExpected(method, expect, shouldNotDeopt, receiver, args); + testAgainstExpected(options, method, expect, shouldNotDeopt, receiver, args); this.argsToBind = null; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/ConstantPhiTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/ConstantPhiTest.java index f358e1008e3..d6fdc91ada2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/ConstantPhiTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/ConstantPhiTest.java @@ -24,15 +24,13 @@ package org.graalvm.compiler.jtt.backend; import static org.graalvm.compiler.api.directives.GraalDirectives.LIKELY_PROBABILITY; import static org.graalvm.compiler.api.directives.GraalDirectives.injectBranchProbability; - +import static org.graalvm.compiler.core.common.GraalOptions.MaximumInliningSize; import java.lang.reflect.Method; import org.junit.Test; -import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.jtt.JTTTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; public class ConstantPhiTest extends JTTTest { @@ -59,24 +57,18 @@ public class ConstantPhiTest extends JTTTest { @Test @SuppressWarnings("try") public void run0() { - try (OverrideScope os = OptionValue.override(GraalOptions.MaximumInliningSize, -1)) { - runTest("test", 0, 0xDEADDEAD); - } + runTest(new OptionValues(getInitialOptions(), MaximumInliningSize, -1), "test", 0, 0xDEADDEAD); } @Test @SuppressWarnings("try") public void run1() { - try (OverrideScope os = OptionValue.override(GraalOptions.MaximumInliningSize, -1)) { - runTest("test", -1, 0xDEADDEAD); - } + runTest(new OptionValues(getInitialOptions(), MaximumInliningSize, -1), "test", -1, 0xDEADDEAD); } @Test @SuppressWarnings("try") public void run2() { - try (OverrideScope os = OptionValue.override(GraalOptions.MaximumInliningSize, -1)) { - runTest("test", 1, 0xDEADDEAD); - } + runTest(new OptionValues(getInitialOptions(), MaximumInliningSize, -1), "test", 1, 0xDEADDEAD); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java index a48e6cd4763..a856a9d518c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/backend/LargeConstantSectionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2017, 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 @@ -22,54 +22,82 @@ */ package org.graalvm.compiler.jtt.backend; -import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC; -import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER; -import static jdk.internal.org.objectweb.asm.Opcodes.ALOAD; -import static jdk.internal.org.objectweb.asm.Opcodes.IFNE; -import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL; -import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC; -import static jdk.internal.org.objectweb.asm.Opcodes.LADD; -import static jdk.internal.org.objectweb.asm.Opcodes.LCMP; -import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_0; -import static jdk.internal.org.objectweb.asm.Opcodes.LLOAD; -import static jdk.internal.org.objectweb.asm.Opcodes.LRETURN; -import static jdk.internal.org.objectweb.asm.Opcodes.RETURN; +import static org.objectweb.asm.Opcodes.ACC_FINAL; +import static org.objectweb.asm.Opcodes.ACC_PUBLIC; +import static org.objectweb.asm.Opcodes.ACC_STATIC; +import static org.objectweb.asm.Opcodes.ACC_SUPER; +import static org.objectweb.asm.Opcodes.ILOAD; +import static org.objectweb.asm.Opcodes.LRETURN; -import org.junit.BeforeClass; -import org.junit.Test; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; -import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.jtt.JTTTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; import org.graalvm.compiler.test.ExportingClassLoader; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameter; +import org.junit.runners.Parameterized.Parameters; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.Label; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.Type; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import junit.framework.AssertionFailedError; +/** + * This test let the compiler deal with a large amount of constant data in a method. This data is + * stored typically in the constant section of the native method. Especially on the SPARC platform + * the backend can address only 8k of memory with an immediate offset. Beyond this barrier, a + * different addressing mode must be used. + * + * In order to do this this test generates a large method containing a large switch statement in + * form of + * + * + * static long run(long a) { + * switch(a) { + * case 1: + * return 0xF0F0F0F0F0L + 1; + * case 2: + * return 0xF0F0F0F0F0L + 2; + * .... + * default: + * return 0; + * } + * + * } + * + * + */ +@RunWith(Parameterized.class) public class LargeConstantSectionTest extends JTTTest { private static final String NAME = "LargeConstantSection"; private static final long LARGE_CONSTANT = 0xF0F0F0F0F0L; private static LargeConstantClassLoader LOADER; + @Parameter(value = 0) public int numberBlocks; - @BeforeClass - public static void before() { + @Parameters(name = "{0}") + public static Collection data() { + List parameters = new ArrayList<>(); + for (int i = 4; i < 13; i += 2) { + parameters.add(new Object[]{1 << i}); + } + return parameters; + } + + @Before + public void before() { LOADER = new LargeConstantClassLoader(LargeConstantSectionTest.class.getClassLoader()); } - public abstract static class LargeConstantAbstract { - public abstract long run(long i); - } - - public static long test(LargeConstantAbstract a, long i) throws Exception { - return a.run(GraalDirectives.opaque(i)); - } - - public static class LargeConstantClassLoader extends ExportingClassLoader { + public class LargeConstantClassLoader extends ExportingClassLoader { public LargeConstantClassLoader(ClassLoader parent) { super(parent); } @@ -77,54 +105,38 @@ public class LargeConstantSectionTest extends JTTTest { @Override protected Class findClass(String name) throws ClassNotFoundException { if (name.equals(NAME)) { - String graalDirectivesClassName = GraalDirectives.class.getName().replace('.', '/'); - int numberIfBlocks = 1100; // Each if block contains three constants ClassWriter cw = new ClassWriter(0); MethodVisitor mv; - String abstractClassName = Type.getInternalName(LargeConstantAbstract.class); - cw.visit(52, ACC_PUBLIC + ACC_SUPER, NAME, null, abstractClassName, null); + cw.visit(52, ACC_PUBLIC + ACC_SUPER, NAME, null, "java/lang/Object", null); - mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv = cw.visitMethod(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, "run", "(I)J", null, null); mv.visitCode(); - Label l0 = new Label(); - mv.visitLabel(l0); - mv.visitVarInsn(ALOAD, 0); - mv.visitMethodInsn(INVOKESPECIAL, abstractClassName, "", "()V", false); - mv.visitInsn(RETURN); - Label l1 = new Label(); - mv.visitLabel(l1); - mv.visitMaxs(1, 1); - mv.visitEnd(); - - mv = cw.visitMethod(ACC_PUBLIC, "run", "(J)J", null, null); - mv.visitCode(); - Label nextIf = new Label(); - for (int i = 0; i < numberIfBlocks; i++) { - mv.visitLabel(nextIf); - mv.visitFrame(Opcodes.F_NEW, 2, new Object[]{abstractClassName, Opcodes.LONG}, 0, new Object[]{}); - mv.visitVarInsn(LLOAD, 1); + Label begin = new Label(); + mv.visitLabel(begin); + mv.visitVarInsn(ILOAD, 0); + Label[] labels = new Label[numberBlocks]; + int[] keys = new int[numberBlocks]; + for (int i = 0; i < labels.length; i++) { + labels[i] = new Label(); + keys[i] = i; + } + Label defaultLabel = new Label(); + mv.visitLookupSwitchInsn(defaultLabel, keys, labels); + for (int i = 0; i < labels.length; i++) { + mv.visitLabel(labels[i]); + mv.visitFrame(Opcodes.F_NEW, 1, new Object[]{Opcodes.INTEGER}, 0, new Object[]{}); mv.visitLdcInsn(new Long(LARGE_CONSTANT + i)); - mv.visitInsn(LCMP); - nextIf = new Label(); - mv.visitJumpInsn(IFNE, nextIf); - mv.visitLdcInsn(new Long(LARGE_CONSTANT + i + numberIfBlocks)); - mv.visitMethodInsn(INVOKESTATIC, graalDirectivesClassName, "opaque", "(J)J", false); - mv.visitLdcInsn(new Long(LARGE_CONSTANT + i + numberIfBlocks * 2)); - mv.visitMethodInsn(INVOKESTATIC, graalDirectivesClassName, "opaque", "(J)J", false); - mv.visitInsn(LADD); mv.visitInsn(LRETURN); } - mv.visitLabel(nextIf); - mv.visitFrame(Opcodes.F_NEW, 2, new Object[]{abstractClassName, Opcodes.LONG}, 0, new Object[]{}); - mv.visitInsn(LCONST_0); + mv.visitLabel(defaultLabel); + mv.visitFrame(Opcodes.F_NEW, 1, new Object[]{Opcodes.INTEGER}, 0, new Object[]{}); + mv.visitLdcInsn(new Long(3L)); mv.visitInsn(LRETURN); - Label l9 = new Label(); - mv.visitLabel(l9); - mv.visitMaxs(4, 6); + Label end = new Label(); + mv.visitLabel(end); + mv.visitLocalVariable("a", "I", null, begin, end, 0); + mv.visitMaxs(2, 1); mv.visitEnd(); - - cw.visitEnd(); - byte[] bytes = cw.toByteArray(); return defineClass(name, bytes, 0, bytes.length); } else { @@ -136,8 +148,20 @@ public class LargeConstantSectionTest extends JTTTest { @Test @SuppressWarnings("try") public void run0() throws Exception { - try (OverrideScope os = OptionValue.override(GraalOptions.InlineEverything, true)) { - runTest("test", LOADER.findClass(NAME).newInstance(), 0L); + test("run", numberBlocks - 3); + } + + @Override + protected ResolvedJavaMethod getResolvedJavaMethod(String methodName) { + try { + for (Method method : LOADER.findClass(NAME).getDeclaredMethods()) { + if (method.getName().equals(methodName)) { + return asResolvedJavaMethod(method); + } + } + } catch (ClassNotFoundException e) { + throw new AssertionFailedError("Cannot find class " + NAME); } + throw GraalError.shouldNotReachHere(); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof.java index 4545fdbc1b1..a2570035d21 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof.java @@ -76,4 +76,20 @@ public class BC_instanceof extends JTTTest { runTest("test", 4); } + // Checkstyle: stop + // Need to stop checkstyle due to empty if constructs. + public static boolean testEmpty(Object obj) { + if (obj instanceof TestClass) { + } + + if (!(obj instanceof TestClass)) { + } + return true; + } + // Checkstyle: resume + + @Test + public void run5() throws Throwable { + runTest("testEmpty", object2); + } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof01.java index 791ee24aed6..599dce74853 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_instanceof01.java @@ -26,8 +26,7 @@ import org.junit.Test; import org.graalvm.compiler.core.phases.HighTier; import org.graalvm.compiler.jtt.JTTTest; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.tiers.Suites; /** @@ -89,10 +88,8 @@ public class BC_instanceof01 extends JTTTest { @Override @SuppressWarnings("try") - protected Suites getSuites() { - try (OverrideScope scope = OptionValue.override(HighTier.Options.Inline, false)) { - return super.getSuites(); - } + protected Suites createSuites(OptionValues options) { + return super.createSuites(new OptionValues(options, HighTier.Options.Inline, false)); } @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_newarray_02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_newarray_02.java new file mode 100644 index 00000000000..41c6d25518d --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/bytecode/BC_newarray_02.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.jtt.bytecode; + +import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; + +public class BC_newarray_02 extends JTTTest { + public static byte[] test(int l) { + return new byte[l]; + } + + @Test + public void testZero() { + runTest("test", 0); + } + + @Test + public void testOne() { + runTest("test", 1); + } + + @Test + public void testNegative() { + runTest("test", -1); + } + + @Test + public void testLarge() { + runTest("test", 17 * 1024 * 1024); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/BC_getfield1.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/BC_getfield1.java index 1753afa108a..783aa17506e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/BC_getfield1.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/BC_getfield1.java @@ -47,7 +47,7 @@ public class BC_getfield1 extends JTTTest { @Test public void run1() throws Throwable { // tests that the null check isn't removed along with the read - runTest(EMPTY, true, true, "test", (Object) null); + runTest(getInitialOptions(), EMPTY, true, true, "test", (Object) null); } @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java index ac939571007..b140a67742e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/except/UntrustedInterfaces.java @@ -22,16 +22,14 @@ */ package org.graalvm.compiler.jtt.except; -import org.junit.BeforeClass; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; import org.graalvm.compiler.test.ExportingClassLoader; - -import jdk.internal.org.objectweb.asm.ClassWriter; -import jdk.internal.org.objectweb.asm.MethodVisitor; -import jdk.internal.org.objectweb.asm.Opcodes; -import jdk.internal.org.objectweb.asm.Type; +import org.junit.BeforeClass; +import org.junit.Test; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; public class UntrustedInterfaces extends JTTTest { diff --git a/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedVM.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/NotOnDebug.java similarity index 70% rename from hotspot/test/compiler/testlibrary/rtm/predicate/SupportedVM.java rename to hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/NotOnDebug.java index fee36b9e5c1..9d4462c5a46 100644 --- a/hotspot/test/compiler/testlibrary/rtm/predicate/SupportedVM.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/NotOnDebug.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,16 +20,19 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +package org.graalvm.compiler.jtt.hotspot; -package compiler.testlibrary.rtm.predicate; +import org.junit.rules.DisableOnDebug; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; -import jdk.test.lib.Platform; - -import java.util.function.BooleanSupplier; - -public class SupportedVM implements BooleanSupplier { - @Override - public boolean getAsBoolean() { - return Platform.isServer() && !Platform.isEmulatedClient(); +public final class NotOnDebug { + public static TestRule create(Timeout seconds) { + try { + return new DisableOnDebug(seconds); + } catch (LinkageError ex) { + return null; + } } + } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6186134.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6186134.java index df296683e2c..6a64c0ea57f 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6186134.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6186134.java @@ -24,15 +24,18 @@ package org.graalvm.compiler.jtt.hotspot; import java.util.ArrayList; -import org.junit.Before; import org.junit.Test; -import org.graalvm.compiler.core.common.util.ArraySet; import org.graalvm.compiler.jtt.JTTTest; // @formatter:off public class Test6186134 extends JTTTest { + @SuppressWarnings("serial") + public static final class MyArrayList extends ArrayList { + + } + public static class TestClass { int num = 0; @@ -45,8 +48,8 @@ public class Test6186134 extends JTTTest { return num-- > 0; } - public ArrayList test1() { - ArrayList res = new ArrayList<>(); + public MyArrayList test1() { + MyArrayList res = new MyArrayList<>(); int maxResults = Integer.MAX_VALUE; int n = 0; boolean more = more(); @@ -70,12 +73,6 @@ public class Test6186134 extends JTTTest { return 0; } - @Before - public void setUp() { - /* Ensure that ArrayList is _not_ a leaf class (otherwise code installation may fail due to a failed leaf type dependency). */ - UNSAFE.ensureClassInitialized(ArraySet.class); - } - @Test public void run0() throws Throwable { runTest("test", 100); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java index 2467c7753d7..3fcf8bf5666 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java @@ -22,12 +22,16 @@ */ package org.graalvm.compiler.jtt.hotspot; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Test6959129 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + public static long test() { int min = Integer.MAX_VALUE - 30000; int max = Integer.MAX_VALUE; @@ -74,8 +78,9 @@ public class Test6959129 extends JTTTest { return maxmoves; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAccess01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAccess01.java index 815110febe0..73906cd73b2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAccess01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/UnsafeAccess01.java @@ -24,30 +24,25 @@ package org.graalvm.compiler.jtt.jdk; import java.lang.reflect.Field; -import org.junit.Test; - -import sun.misc.Unsafe; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; /* */ public class UnsafeAccess01 extends JTTTest { private static int randomValue = 100; - private static final Unsafe unsafe; private static final long offset; private static Object staticObject = new TestClass(); static { - unsafe = getUnsafe(); Field field = null; try { field = TestClass.class.getDeclaredField("field"); } catch (NoSuchFieldException e) { } catch (SecurityException e) { } - offset = unsafe.objectFieldOffset(field); + offset = UNSAFE.objectFieldOffset(field); } private static class TestClass { @@ -56,20 +51,10 @@ public class UnsafeAccess01 extends JTTTest { public static int test() { final TestClass object = new TestClass(); - final int value = unsafe.getInt(object, offset); + final int value = UNSAFE.getInt(object, offset); return value; } - static Unsafe getUnsafe() { - try { - final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); - unsafeField.setAccessible(true); - return (Unsafe) unsafeField.get(null); - } catch (Exception e) { - throw new Error(e); - } - } - @Test public void run0() throws Throwable { runTest("test"); @@ -86,11 +71,11 @@ public class UnsafeAccess01 extends JTTTest { final int oldValue = ((TestClass) object).field; if (randomValue == 100) { - unsafe.putInt(object, offset, 41); + UNSAFE.putInt(object, offset, 41); } else { - unsafe.putInt(object, offset, 40); + UNSAFE.putInt(object, offset, 40); } - unsafe.putInt(object, offset, 42); + UNSAFE.putInt(object, offset, 42); return oldValue; } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwap.java index 98f0f27cef7..2f1df0cc53e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwap.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwap.java @@ -22,21 +22,17 @@ */ package org.graalvm.compiler.jtt.jdk; -import jdk.vm.ci.meta.ResolvedJavaMethod; - +import org.graalvm.compiler.jtt.JTTTest; import org.junit.Test; -import sun.misc.Unsafe; - -import org.graalvm.compiler.jtt.JTTTest; +import jdk.vm.ci.meta.ResolvedJavaMethod; public class Unsafe_compareAndSwap extends JTTTest { - static final Unsafe unsafe = UnsafeAccess01.getUnsafe(); static final long valueOffset; static { try { - valueOffset = unsafe.objectFieldOffset(Unsafe_compareAndSwap.class.getDeclaredField("value")); + valueOffset = UNSAFE.objectFieldOffset(Unsafe_compareAndSwap.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } @@ -44,9 +40,9 @@ public class Unsafe_compareAndSwap extends JTTTest { public static String test(Unsafe_compareAndSwap u, Object o, String expected, String newValue) { // First arg is not an array - can use a field write barrier - unsafe.compareAndSwapObject(u, valueOffset, expected, newValue); + UNSAFE.compareAndSwapObject(u, valueOffset, expected, newValue); // Not known if first arg is an array - different write barrier may be used - unsafe.compareAndSwapObject(o, valueOffset, expected, newValue); + UNSAFE.compareAndSwapObject(o, valueOffset, expected, newValue); return instance.value; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java index 5d109a8dda3..a69bf2d8059 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java @@ -22,19 +22,16 @@ */ package org.graalvm.compiler.jtt.jdk; -import org.junit.Test; - -import sun.misc.Unsafe; - import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Assume; +import org.junit.Test; public class Unsafe_compareAndSwapNullCheck extends JTTTest { - static final Unsafe unsafe = UnsafeAccess01.getUnsafe(); static final long valueOffset; static { try { - valueOffset = unsafe.objectFieldOffset(Unsafe_compareAndSwap.class.getDeclaredField("value")); + valueOffset = UNSAFE.objectFieldOffset(Unsafe_compareAndSwap.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } @@ -46,11 +43,13 @@ public class Unsafe_compareAndSwapNullCheck extends JTTTest { public static void test(Unsafe_compareAndSwapNullCheck u, long expected, long newValue) { @SuppressWarnings("unused") long l = u.lng; - unsafe.compareAndSwapLong(u, valueOffset, expected, newValue); + UNSAFE.compareAndSwapLong(u, valueOffset, expected, newValue); } @Test public void run0() throws Throwable { - runTest(EMPTY, false, true, "test", null, 1L, 2L); + // GR-2921: Unsafe_compareAndSwapNullCheck test crashes on jdk9 + Assume.assumeTrue(Java8OrEarlier); + runTest(getInitialOptions(), EMPTY, false, true, "test", null, 1L, 2L); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/LambdaEagerTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/LambdaEagerTest.java index cefbae2f970..b7ae49954f6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/LambdaEagerTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/lang/LambdaEagerTest.java @@ -22,21 +22,20 @@ */ package org.graalvm.compiler.jtt.lang; +import static org.graalvm.compiler.core.common.GraalOptions.InlineEverything; + import java.util.EnumSet; import java.util.function.IntBinaryOperator; +import org.graalvm.compiler.core.test.GraalCompilerTest; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.options.OptionValues; +import org.junit.Test; + import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.ResolvedJavaMethod; -import org.junit.Test; - -import org.graalvm.compiler.core.common.GraalOptions; -import org.graalvm.compiler.core.test.GraalCompilerTest; -import org.graalvm.compiler.nodes.StructuredGraph; -import org.graalvm.compiler.options.OptionValue; -import org.graalvm.compiler.options.OptionValue.OverrideScope; - public class LambdaEagerTest extends GraalCompilerTest { private static final EnumSet UNRESOLVED_UNREACHED = EnumSet.of(DeoptimizationReason.Unresolved, DeoptimizationReason.UnreachedCode); @@ -81,9 +80,8 @@ public class LambdaEagerTest extends GraalCompilerTest { @Override @SuppressWarnings("try") - protected InstalledCode getCode(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile) { - try (OverrideScope scope = OptionValue.override(GraalOptions.InlineEverything, true)) { - return super.getCode(installedCodeOwner, graph, forceCompile); - } + protected InstalledCode getCode(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) { + assert graph == null; + return super.getCode(installedCodeOwner, graph, forceCompile, installAsDefault, new OptionValues(options, InlineEverything, true)); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/GuardMovement.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/GuardMovement.java new file mode 100644 index 00000000000..68dacfc81d3 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/GuardMovement.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.jtt.optimize; + +import org.junit.Assert; +import org.junit.Test; + +import static org.graalvm.compiler.core.common.GraalOptions.MaximumInliningSize; +import org.graalvm.compiler.core.common.GraalOptions; +import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.options.OptionValues; + +public class GuardMovement extends JTTTest { + + private static int staticValue; + + private static class A { + int x; + int y; + } + + public int foo(A a) { + Assert.assertNotEquals("a cannot be null, because a field of a is accessed before the call", a, null); + return 42; + } + + @SuppressWarnings("all") + public int test(A a) { + + int value; + int result = 0; + + // Use a condition that folds after floating guards and before guard lowering. + // After disabling PEA and read elimination, the following condition does the trick. + if (staticValue == staticValue) { + // Access a.x to generate a null checked value. + value = a.x; + result = foo(a); + } + + // Access a.y to generate another null checked value. + return result + a.y; + } + + @Test + public void run0() throws Throwable { + OptionValues options = new OptionValues(getInitialOptions(), MaximumInliningSize, -1, GraalOptions.TrivialInliningSize, -1, GraalOptions.PartialEscapeAnalysis, false, + GraalOptions.OptReadElimination, false); + runTest(options, "test", new A()); + runTest(options, "test", new Object[]{null}); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java index b479d7ec5c6..2fa90ad28af 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/NestedLoop_EA.java @@ -29,6 +29,7 @@ import org.junit.Test; import org.graalvm.compiler.jtt.JTTTest; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.virtual.CommitAllocationNode; +import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.BasePhase; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -38,13 +39,13 @@ import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase; public class NestedLoop_EA extends JTTTest { @Override - protected Suites createSuites() { - Suites suites = super.createSuites(); + protected Suites createSuites(OptionValues options) { + Suites suites = super.createSuites(options); ListIterator> position = suites.getHighTier().findPhase(PartialEscapePhase.class); CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); // incremental canonicalizer of PEA is missing some important canonicalization (TODO?) position.add(canonicalizer); - position.add(new PartialEscapePhase(true, canonicalizer)); + position.add(new PartialEscapePhase(true, canonicalizer, options)); return suites; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/UnsafeDeopt.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/UnsafeDeopt.java index 929bb24b4c7..6275a2009d2 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/UnsafeDeopt.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/UnsafeDeopt.java @@ -22,44 +22,30 @@ */ package org.graalvm.compiler.jtt.optimize; -import java.lang.reflect.Field; import java.nio.ByteBuffer; -import org.junit.Test; -import org.junit.internal.AssumptionViolatedException; - import org.graalvm.compiler.api.directives.GraalDirectives; import org.graalvm.compiler.jtt.JTTTest; +import org.junit.Test; +import org.junit.internal.AssumptionViolatedException; import jdk.vm.ci.meta.ResolvedJavaMethod; -import sun.misc.Unsafe; public class UnsafeDeopt extends JTTTest { - private static final Unsafe unsafe; - - static { - try { - final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); - unsafeField.setAccessible(true); - unsafe = (Unsafe) unsafeField.get(null); - } catch (Exception e) { - throw new Error(e); - } - } public static int readWriteReadUnsafe(long addr, int m) { - int original = unsafe.getInt(addr); + int original = UNSAFE.getInt(addr); if (original != 0) { return -m; } - unsafe.putInt(addr, m); + UNSAFE.putInt(addr, m); if (m > 10) { if (m > 20) { GraalDirectives.deoptimize(); } - unsafe.putInt(addr + 4, m); + UNSAFE.putInt(addr + 4, m); } - return unsafe.getInt(addr); + return UNSAFE.getInt(addr); } public static int readWriteReadByteBuffer(ByteBuffer buffer, int m) { @@ -78,13 +64,13 @@ public class UnsafeDeopt extends JTTTest { } public long createBuffer() { - long addr = unsafe.allocateMemory(32); - unsafe.setMemory(addr, 32, (byte) 0); + long addr = UNSAFE.allocateMemory(32); + UNSAFE.setMemory(addr, 32, (byte) 0); return addr; } public void disposeBuffer(long addr) { - unsafe.freeMemory(addr); + UNSAFE.freeMemory(addr); } @Test diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/VN_Double03.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/VN_Double03.java new file mode 100644 index 00000000000..e7ec7263a4f --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/optimize/VN_Double03.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.jtt.optimize; + +import org.junit.Test; + +import org.graalvm.compiler.jtt.JTTTest; + +/* + * Tests optimization of float operations. + */ +public class VN_Double03 extends JTTTest { + + public static double test(double arg) { + if (arg == -0.0d) { + return arg; + } + return 0; + } + + @Test + public void run0() throws Throwable { + runTest("test", -0.0d); + } + + @Test + public void run1() throws Throwable { + runTest("test", 0.0d); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java index d42b57e7fe8..30d049ff986 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public final class Monitor_contended01 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + private static class TestClass implements Runnable { boolean started = false; boolean acquired = false; @@ -75,8 +80,9 @@ public final class Monitor_contended01 extends JTTTest { return object.acquired; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java index 8c8978000a8..aa4eebcc25a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Monitor_notowner01 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + static Object monitor = new Object(); static Object finished = new Object(); @@ -64,8 +69,9 @@ public class Monitor_notowner01 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java index af35abebd89..a4a31b4339b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public final class Monitorenter01 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + static final Object object = new Object(); public static boolean test() { @@ -41,8 +46,9 @@ public final class Monitorenter01 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java index f688227fc39..5bbd75a619d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public final class Monitorenter02 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + static final Object object = new Object(); public static boolean test() { @@ -45,8 +50,9 @@ public final class Monitorenter02 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java index dc6eae1e25c..9fb9e0e357e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Object_wait01 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + private static class TestClass implements Runnable { @Override public void run() { @@ -60,23 +65,27 @@ public class Object_wait01 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 0); } - @Test(timeout = 20000) + @Test public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 1); } - @Test(timeout = 20000) + @Test public void run2() throws Throwable { + initializeForTimeout(); runTest("test", 3); } - @Test(timeout = 20000) + @Test public void run3() throws Throwable { + initializeForTimeout(); runTest("test", 15); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java index ccd61b3456b..7c5b45245ca 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Object_wait02 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + private static class TestClass implements Runnable { @Override public void run() { @@ -61,18 +66,21 @@ public class Object_wait02 extends JTTTest { return done; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 0); } - @Test(timeout = 20000) + @Test public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 1); } - @Test(timeout = 20000) + @Test public void run2() throws Throwable { + initializeForTimeout(); runTest("test", 2); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java index d8376621d5d..f927aeef86b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java @@ -24,12 +24,32 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - +import org.graalvm.compiler.core.common.CancellationBailoutException; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.nodes.Cancellable; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; + +import jdk.vm.ci.meta.ResolvedJavaMethod; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; public class Object_wait03 extends JTTTest { + /** + * Timeout for compilation. + */ + static final long COMPILATION_TIMEOUT_MS = 15_000; + + /** + * Total timeout for compilation and execution of compiled code. + */ + static final long TIMEOUT_MS = COMPILATION_TIMEOUT_MS * 2; + + @Rule public TestRule timeout = NotOnDebug.create(Timeout.millis(TIMEOUT_MS)); + private static class TestClass implements Runnable { @Override public void run() { @@ -67,19 +87,62 @@ public class Object_wait03 extends JTTTest { } } - @Test(timeout = 20000) + static class CompilationTimeout extends Thread implements Cancellable { + boolean timedOut; + final long durationMS; + + CompilationTimeout(long durationMS) { + super("CompilationTimeout-" + durationMS + "ms"); + this.durationMS = durationMS; + setDaemon(true); + start(); + } + + @Override + public void run() { + try { + Thread.sleep(durationMS); + } catch (InterruptedException e) { + } + timedOut = true; + } + + @Override + public boolean isCancelled() { + return timedOut; + } + } + + @Override + protected Cancellable getCancellable(ResolvedJavaMethod method) { + return new CompilationTimeout(COMPILATION_TIMEOUT_MS); + } + + private void run(int i) throws Throwable { + initializeForTimeout(); + try { + runTest("test", i); + } catch (CancellationBailoutException e) { + String message = String.format("Compilation cancelled after " + COMPILATION_TIMEOUT_MS + " ms"); + // For diagnosing expectedly long compilations (GR-3853) + DebugContext debug = getDebugContext(); + debug.forceDump(lastCompiledGraph, message); + throw new AssertionError(message, e); + } + } + + @Test public void run0() throws Throwable { - runTest("test", 0); + run(0); } - @Test(timeout = 20000) + @Test public void run1() throws Throwable { - runTest("test", 1); + run(1); } - @Test(timeout = 20000) + @Test public void run2() throws Throwable { - runTest("test", 2); + run(2); } - } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java index 925dada3ef5..ee6ccef8a34 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Object_wait04 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + private static class TestClass implements Runnable { @Override public void run() { @@ -71,33 +76,39 @@ public class Object_wait04 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 0); } - @Test(timeout = 20000) + @Test public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 1); } - @Test(timeout = 20000) + @Test public void run2() throws Throwable { + initializeForTimeout(); runTest("test", 2); } - @Test(timeout = 20000) + @Test public void run3() throws Throwable { + initializeForTimeout(); runTest("test", 3); } - @Test(timeout = 20000) + @Test public void run4() throws Throwable { + initializeForTimeout(); runTest("test", 4); } - @Test(timeout = 20000) + @Test public void run5() throws Throwable { + initializeForTimeout(); runTest("test", 5); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java index fdb58db5814..beacb41f66c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java @@ -24,9 +24,12 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; /** * Inspired by {@code com.sun.media.sound.DirectAudioDevice$DirectDL.drain()}. @@ -36,6 +39,8 @@ import org.graalvm.compiler.jtt.JTTTest; */ public final class SynchronizedLoopExit01 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + protected Object object = new Object(); protected volatile boolean drained = false; protected volatile boolean someBoolean = true; @@ -53,8 +58,9 @@ public final class SynchronizedLoopExit01 extends JTTTest { return b; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java index 41edeed4e92..180d7e10ef5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java @@ -26,14 +26,19 @@ package org.graalvm.compiler.jtt.threads; -import org.junit.Assert; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Assert; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; //Test all, mainly monitors public class Thread_isInterrupted02 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + private static final Object start = new Object(); private static final Object end = new Object(); private static int waitTime; @@ -103,13 +108,15 @@ public class Thread_isInterrupted02 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 0, 0); } - @Test(timeout = 20000) + @Test public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 1, 500); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java index 6e2b3c291b4..70f56771249 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java @@ -22,9 +22,12 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; /* */ @@ -32,6 +35,8 @@ import org.graalvm.compiler.jtt.JTTTest; // Interrupted while sleeping, throws an interrupted exception public class Thread_isInterrupted03 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + public static boolean test() throws InterruptedException { final Thread1 thread = new Thread1(); thread.start(); @@ -69,8 +74,9 @@ public class Thread_isInterrupted03 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java index 9e70ded4d6b..95239c5c9c1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java @@ -22,9 +22,12 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; /* */ @@ -32,6 +35,8 @@ import org.graalvm.compiler.jtt.JTTTest; // Interrupted during wait, with interrupter joining public class Thread_isInterrupted05 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + public static boolean test() throws InterruptedException { final WaitInterruptee waitInterruptee = new WaitInterruptee(); waitInterruptee.start(); @@ -67,8 +72,9 @@ public class Thread_isInterrupted05 extends JTTTest { } } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java index 1937618b869..5e7f746070c 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java @@ -24,12 +24,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Thread_join01 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + private static class TestClass implements Runnable { @Override public void run() { @@ -47,8 +52,9 @@ public class Thread_join01 extends JTTTest { return cont; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java index 824ecf75b10..9220b6da8c0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java @@ -27,12 +27,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Thread_join02 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + private static class TestClass implements Runnable { @Override public void run() { @@ -54,8 +59,9 @@ public class Thread_join02 extends JTTTest { return cont; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java index 1e815b64c7d..e6c62e099b0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java @@ -27,12 +27,17 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public class Thread_join03 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + private static class TestClass implements Runnable { @Override public void run() { @@ -51,8 +56,9 @@ public class Thread_join03 extends JTTTest { return cont; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java index e2245488715..919f07c425a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java @@ -24,30 +24,38 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public final class Thread_sleep01 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + public static boolean test(int i) throws InterruptedException { final long before = System.currentTimeMillis(); Thread.sleep(i); return System.currentTimeMillis() - before >= i; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test", 10); } - @Test(timeout = 20000) + @Test public void run1() throws Throwable { + initializeForTimeout(); runTest("test", 20); } - @Test(timeout = 20000) + @Test public void run2() throws Throwable { + initializeForTimeout(); runTest("test", 100); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java index 0c6380150a8..bce920883b5 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java @@ -24,19 +24,25 @@ */ package org.graalvm.compiler.jtt.threads; -import org.junit.Test; - import org.graalvm.compiler.jtt.JTTTest; +import org.graalvm.compiler.jtt.hotspot.NotOnDebug; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.rules.Timeout; public final class Thread_yield01 extends JTTTest { + @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20)); + public static boolean test() { Thread.yield(); return true; } - @Test(timeout = 20000) + @Test public void run0() throws Throwable { + initializeForTimeout(); runTest("test"); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AddressValue.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AddressValue.java index a6c6ffaccf5..e2b6999f873 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AddressValue.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AddressValue.java @@ -46,20 +46,20 @@ public final class AArch64AddressValue extends CompositeValue { @Component({OperandFlag.REG, OperandFlag.ILLEGAL}) protected AllocatableValue base; @Component({OperandFlag.REG, OperandFlag.ILLEGAL}) protected AllocatableValue offset; - private final int immediate; + private final int displacement; /** * Whether register offset should be scaled or not. */ - private final boolean scaled; + private final int scaleFactor; private final AddressingMode addressingMode; - public AArch64AddressValue(ValueKind kind, AllocatableValue base, AllocatableValue offset, int immediate, boolean scaled, AddressingMode addressingMode) { + public AArch64AddressValue(ValueKind kind, AllocatableValue base, AllocatableValue offset, int displacement, int scaleFactor, AddressingMode addressingMode) { super(kind); this.base = base; this.offset = offset; - this.immediate = immediate; - this.scaled = scaled; + this.displacement = displacement; + this.scaleFactor = scaleFactor; this.addressingMode = addressingMode; } @@ -79,12 +79,16 @@ public final class AArch64AddressValue extends CompositeValue { return offset; } - public int getImmediate() { - return immediate; + public int getDisplacement() { + return displacement; } public boolean isScaled() { - return scaled; + return scaleFactor != 1; + } + + public int getScaleFactor() { + return scaleFactor; } public AddressingMode getAddressingMode() { @@ -95,7 +99,7 @@ public final class AArch64AddressValue extends CompositeValue { Register baseReg = toRegister(base); Register offsetReg = toRegister(offset); AArch64Assembler.ExtendType extendType = addressingMode == AddressingMode.EXTENDED_REGISTER_OFFSET ? ExtendType.SXTW : null; - return AArch64Address.createAddress(addressingMode, baseReg, offsetReg, immediate, scaled, extendType); + return AArch64Address.createAddress(addressingMode, baseReg, offsetReg, displacement / scaleFactor, isScaled(), extendType); } @Override @@ -103,7 +107,7 @@ public final class AArch64AddressValue extends CompositeValue { AllocatableValue newBase = (AllocatableValue) proc.doValue(inst, base, mode, flags); AllocatableValue newOffset = (AllocatableValue) proc.doValue(inst, offset, mode, flags); if (!base.identityEquals(newBase) || !offset.identityEquals(newOffset)) { - return new AArch64AddressValue(getValueKind(), newBase, newOffset, immediate, scaled, addressingMode); + return new AArch64AddressValue(getValueKind(), newBase, newOffset, displacement, scaleFactor, addressingMode); } return this; } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java index caf734f88e6..cbe7676a382 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArithmeticOp.java @@ -51,6 +51,7 @@ public enum AArch64ArithmeticOp { SUB(ARITHMETIC), SUBS(ARITHMETIC), MUL, + MULVS, DIV, SMULH, UMULH, @@ -176,6 +177,14 @@ public enum AArch64ArithmeticOp { assert AArch64MacroAssembler.isArithmeticImmediate(b.asLong()); masm.sub(size, dst, src, (int) b.asLong()); break; + case ADDS: + assert AArch64MacroAssembler.isArithmeticImmediate(b.asLong()); + masm.adds(size, dst, src, (int) b.asLong()); + break; + case SUBS: + assert AArch64MacroAssembler.isArithmeticImmediate(b.asLong()); + masm.subs(size, dst, src, (int) b.asLong()); + break; case AND: // XXX Should this be handled somewhere else? if (size == 32 && b.asLong() == 0xFFFF_FFFFL) { @@ -291,6 +300,9 @@ public enum AArch64ArithmeticOp { case FDIV: masm.fdiv(size, dst, src1, src2); break; + case MULVS: + masm.mulvs(size, dst, src1, src2); + break; default: throw GraalError.shouldNotReachHere("op=" + op.name()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java new file mode 100644 index 00000000000..31476aff584 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayEqualsOp.java @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.aarch64; + +import static jdk.vm.ci.aarch64.AArch64.zr; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; + +import java.lang.reflect.Array; +import java.lang.reflect.Field; + +import org.graalvm.compiler.asm.Label; +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.ScratchRegister; +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.compiler.lir.gen.LIRGeneratorTool; + +import jdk.vm.ci.code.Register; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.Value; +import sun.misc.Unsafe; + +/** + * Emits code which compares two arrays of the same length. If the CPU supports any vector + * instructions specialized code is emitted to leverage these instructions. + */ +@Opcode("ARRAY_EQUALS") +public final class AArch64ArrayEqualsOp extends AArch64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64ArrayEqualsOp.class); + + private final JavaKind kind; + private final int arrayBaseOffset; + private final int arrayIndexScale; + + @Def({REG}) protected Value resultValue; + @Alive({REG}) protected Value array1Value; + @Alive({REG}) protected Value array2Value; + @Alive({REG}) protected Value lengthValue; + @Temp({REG}) protected Value temp1; + @Temp({REG}) protected Value temp2; + @Temp({REG}) protected Value temp3; + @Temp({REG}) protected Value temp4; + + public AArch64ArrayEqualsOp(LIRGeneratorTool tool, JavaKind kind, Value result, Value array1, Value array2, Value length) { + super(TYPE); + this.kind = kind; + + Class arrayClass = Array.newInstance(kind.toJavaClass(), 0).getClass(); + this.arrayBaseOffset = UNSAFE.arrayBaseOffset(arrayClass); + this.arrayIndexScale = UNSAFE.arrayIndexScale(arrayClass); + + this.resultValue = result; + this.array1Value = array1; + this.array2Value = array2; + this.lengthValue = length; + + // Allocate some temporaries. + this.temp1 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind())); + this.temp2 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind())); + this.temp3 = tool.newVariable(LIRKind.value(tool.target().arch.getWordKind())); + this.temp4 = tool.newVariable(LIRKind.value(tool.target().arch.getWordKind())); + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + Register result = asRegister(resultValue); + Register array1 = asRegister(temp1); + Register array2 = asRegister(temp2); + Register length = asRegister(temp3); + + Label breakLabel = new Label(); + + try (ScratchRegister sc1 = masm.getScratchRegister()) { + Register rscratch1 = sc1.getRegister(); + // Load array base addresses. + masm.lea(array1, AArch64Address.createUnscaledImmediateAddress(asRegister(array1Value), arrayBaseOffset)); + masm.lea(array2, AArch64Address.createUnscaledImmediateAddress(asRegister(array2Value), arrayBaseOffset)); + + // Get array length in bytes. + masm.mov(rscratch1, arrayIndexScale); + masm.smaddl(length, asRegister(lengthValue), rscratch1, zr); + masm.mov(64, result, length); // copy + + emit8ByteCompare(crb, masm, result, array1, array2, length, breakLabel, rscratch1); + emitTailCompares(masm, result, array1, array2, breakLabel, rscratch1); + + // Return: rscratch1 is non-zero iff the arrays differ + masm.bind(breakLabel); + masm.cmp(64, rscratch1, zr); + masm.cset(result, ConditionFlag.EQ); + } + } + + /** + * Vector size used in {@link #emit8ByteCompare}. + */ + private static final int VECTOR_SIZE = 8; + + /** + * Emits code that uses 8-byte vector compares. + * + */ + private void emit8ByteCompare(CompilationResultBuilder crb, AArch64MacroAssembler masm, Register result, Register array1, Register array2, Register length, Label breakLabel, + Register rscratch1) { + Label loop = new Label(); + Label compareTail = new Label(); + + Register temp = asRegister(temp4); + + masm.and(64, result, result, VECTOR_SIZE - 1); // tail count (in bytes) + masm.ands(64, length, length, ~(VECTOR_SIZE - 1)); // vector count (in bytes) + masm.branchConditionally(ConditionFlag.EQ, compareTail); + + masm.lea(array1, AArch64Address.createRegisterOffsetAddress(array1, length, false)); + masm.lea(array2, AArch64Address.createRegisterOffsetAddress(array2, length, false)); + masm.sub(64, length, zr, length); + + // Align the main loop + masm.align(crb.target.wordSize * 2); + masm.bind(loop); + masm.ldr(64, temp, AArch64Address.createRegisterOffsetAddress(array1, length, false)); + masm.ldr(64, rscratch1, AArch64Address.createRegisterOffsetAddress(array2, length, false)); + masm.eor(64, rscratch1, temp, rscratch1); + masm.cbnz(64, rscratch1, breakLabel); + masm.add(64, length, length, VECTOR_SIZE); + masm.cbnz(64, length, loop); + + masm.cbz(64, result, breakLabel); + + /* + * Compare the remaining bytes with an unaligned memory load aligned to the end of the + * array. + */ + masm.lea(array1, AArch64Address.createUnscaledImmediateAddress(array1, -VECTOR_SIZE)); + masm.lea(array2, AArch64Address.createUnscaledImmediateAddress(array2, -VECTOR_SIZE)); + masm.ldr(64, temp, AArch64Address.createRegisterOffsetAddress(array1, result, false)); + masm.ldr(64, rscratch1, AArch64Address.createRegisterOffsetAddress(array2, result, false)); + masm.eor(64, rscratch1, temp, rscratch1); + masm.jmp(breakLabel); + + masm.bind(compareTail); + } + + /** + * Emits code to compare the remaining 1 to 4 bytes. + * + */ + private void emitTailCompares(AArch64MacroAssembler masm, Register result, Register array1, Register array2, Label breakLabel, Register rscratch1) { + Label compare2Bytes = new Label(); + Label compare1Byte = new Label(); + Label end = new Label(); + + Register temp = asRegister(temp4); + + if (kind.getByteCount() <= 4) { + // Compare trailing 4 bytes, if any. + masm.ands(32, zr, result, 4); + masm.branchConditionally(ConditionFlag.EQ, compare2Bytes); + masm.ldr(32, temp, AArch64Address.createPostIndexedImmediateAddress(array1, 4)); + masm.ldr(32, rscratch1, AArch64Address.createPostIndexedImmediateAddress(array2, 4)); + masm.eor(32, rscratch1, temp, rscratch1); + masm.cbnz(32, rscratch1, breakLabel); + + if (kind.getByteCount() <= 2) { + // Compare trailing 2 bytes, if any. + masm.bind(compare2Bytes); + masm.ands(32, zr, result, 2); + masm.branchConditionally(ConditionFlag.EQ, compare1Byte); + masm.ldr(16, temp, AArch64Address.createPostIndexedImmediateAddress(array1, 2)); + masm.ldr(16, rscratch1, AArch64Address.createPostIndexedImmediateAddress(array2, 2)); + masm.eor(32, rscratch1, temp, rscratch1); + masm.cbnz(32, rscratch1, breakLabel); + + // The one-byte tail compare is only required for boolean and byte arrays. + if (kind.getByteCount() <= 1) { + // Compare trailing byte, if any. + masm.bind(compare1Byte); + masm.ands(32, zr, result, 1); + masm.branchConditionally(ConditionFlag.EQ, end); + masm.ldr(8, temp, AArch64Address.createBaseRegisterOnlyAddress(array1)); + masm.ldr(8, rscratch1, AArch64Address.createBaseRegisterOnlyAddress(array2)); + masm.eor(32, rscratch1, temp, rscratch1); + masm.cbnz(32, rscratch1, breakLabel); + } else { + masm.bind(compare1Byte); + } + } else { + masm.bind(compare2Bytes); + } + } + masm.bind(end); + masm.mov(64, rscratch1, zr); + } + + private static final Unsafe UNSAFE = initUnsafe(); + + private static Unsafe initUnsafe() { + try { + return Unsafe.getUnsafe(); + } catch (SecurityException se) { + try { + Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); + theUnsafe.setAccessible(true); + return (Unsafe) theUnsafe.get(Unsafe.class); + } catch (Exception e) { + throw new RuntimeException("exception while trying to get Unsafe", e); + } + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java index 31b6f4e6edf..45bd9330473 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BitManipulationOp.java @@ -39,7 +39,7 @@ import jdk.vm.ci.meta.AllocatableValue; */ public class AArch64BitManipulationOp extends AArch64LIRInstruction { public enum BitManipulationOpCode { - BSF, + CTZ, BSR, BSWP, CLZ, @@ -62,7 +62,7 @@ public class AArch64BitManipulationOp extends AArch64LIRInstruction { public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register dst = asRegister(result); Register src = asRegister(input); - final int size = result.getPlatformKind().getSizeInBytes() * Byte.SIZE; + final int size = input.getPlatformKind().getSizeInBytes() * Byte.SIZE; switch (opcode) { case CLZ: masm.clz(size, dst, src); @@ -73,9 +73,9 @@ public class AArch64BitManipulationOp extends AArch64LIRInstruction { masm.neg(size, dst, dst); masm.add(size, dst, dst, size - 1); break; - case BSF: - // BSF == CLZ(rev(input)) - masm.rev(size, dst, src); + case CTZ: + // CTZ == CLZ(rbit(input)) + masm.rbit(size, dst, src); masm.clz(size, dst, dst); break; case BSWP: diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BlockEndOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BlockEndOp.java index 115e57882b8..5147d96cfcf 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BlockEndOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64BlockEndOp.java @@ -24,11 +24,12 @@ package org.graalvm.compiler.lir.aarch64; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.StandardOp.AbstractBlockEndOp; +import org.graalvm.compiler.lir.StandardOp.BlockEndOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -public abstract class AArch64BlockEndOp extends AbstractBlockEndOp { +public abstract class AArch64BlockEndOp extends LIRInstruction implements BlockEndOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64BlockEndOp.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ByteSwapOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ByteSwapOp.java new file mode 100644 index 00000000000..0eae02eae13 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ByteSwapOp.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.aarch64; + +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.aarch64.AArch64Kind; +import jdk.vm.ci.code.ValueUtil; +import jdk.vm.ci.meta.Value; + +@Opcode("BSWAP") +public final class AArch64ByteSwapOp extends AArch64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64ByteSwapOp.class); + + @Def({OperandFlag.REG, OperandFlag.HINT}) protected Value result; + @Use protected Value input; + + public AArch64ByteSwapOp(Value result, Value input) { + super(TYPE); + this.result = result; + this.input = input; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + switch ((AArch64Kind) input.getPlatformKind()) { + case DWORD: + masm.rev(32, ValueUtil.asRegister(result), ValueUtil.asRegister(input)); + break; + case QWORD: + masm.rev(64, ValueUtil.asRegister(result), ValueUtil.asRegister(input)); + break; + default: + throw GraalError.shouldNotReachHere(); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64CCall.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64CCall.java new file mode 100644 index 00000000000..b2fef6e1084 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64CCall.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.aarch64; + +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; + +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.ValueUtil; +import jdk.vm.ci.meta.Value; + +public final class AArch64CCall extends AArch64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64CCall.class); + + @Def({REG, ILLEGAL}) protected Value result; + @Use({REG, STACK}) protected Value[] parameters; + @Use({REG}) protected Value functionPtr; + + public AArch64CCall(Value result, Value functionPtr, Value[] parameters) { + super(TYPE); + this.result = result; + this.functionPtr = functionPtr; + this.parameters = parameters; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + directCall(masm); + } + + private void directCall(AArch64MacroAssembler masm) { + Register reg = ValueUtil.asRegister(functionPtr); + masm.blr(reg); + masm.ensureUniquePC(); + } + + @Override + public boolean destroysCallerSavedRegisters() { + return true; + } + +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Compare.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Compare.java index 60a6fc90eba..18c96278670 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Compare.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Compare.java @@ -29,7 +29,7 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.core.common.calc.Condition; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java index 9604854e9e9..d06f4ccfa00 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ControlFlow.java @@ -24,16 +24,17 @@ package org.graalvm.compiler.lir.aarch64; import static jdk.vm.ci.code.ValueUtil.asAllocatableValue; import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import java.util.function.Function; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; -import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.aarch64.AArch64Assembler; import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ExtendType; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; -import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.PatchLabelKind; import org.graalvm.compiler.code.CompilationResult.JumpTable; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.core.common.calc.Condition; @@ -234,61 +235,51 @@ public class AArch64ControlFlow { } } - public static class TableSwitchOp extends AArch64BlockEndOp implements StandardOp.BlockEndOp { + public static final class TableSwitchOp extends AArch64BlockEndOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(TableSwitchOp.class); - private final int lowKey; private final LabelRef defaultTarget; private final LabelRef[] targets; - @Alive protected Variable keyValue; - @Temp protected Variable scratchValue; + @Use protected Value index; + @Temp({REG, HINT}) protected Value idxScratch; + @Temp protected Value scratch; - public TableSwitchOp(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Variable key, Variable scratch) { + public TableSwitchOp(final int lowKey, final LabelRef defaultTarget, final LabelRef[] targets, Value index, Variable scratch, Variable idxScratch) { super(TYPE); this.lowKey = lowKey; this.defaultTarget = defaultTarget; this.targets = targets; - this.keyValue = key; - this.scratchValue = scratch; + this.index = index; + this.scratch = scratch; + this.idxScratch = idxScratch; } @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - Register key = asRegister(keyValue); - Register scratch = asRegister(scratchValue); - if (lowKey != 0) { - if (AArch64MacroAssembler.isArithmeticImmediate(lowKey)) { - masm.sub(32, key, key, lowKey); - } else { - ConstantValue constVal = new ConstantValue(LIRKind.value(AArch64Kind.WORD), JavaConstant.forInt(lowKey)); - AArch64Move.move(crb, masm, scratchValue, constVal); - masm.sub(32, key, key, scratch); - } - } + Register indexReg = asRegister(index, AArch64Kind.DWORD); + Register idxScratchReg = asRegister(idxScratch, AArch64Kind.DWORD); + Register scratchReg = asRegister(scratch, AArch64Kind.QWORD); + + // Compare index against jump table bounds + int highKey = lowKey + targets.length - 1; + masm.sub(32, idxScratchReg, indexReg, lowKey); + masm.cmp(32, idxScratchReg, highKey - lowKey); + + // Jump to default target if index is not within the jump table if (defaultTarget != null) { - // if key is not in table range, jump to default target if it exists. - ConstantValue constVal = new ConstantValue(LIRKind.value(AArch64Kind.WORD), JavaConstant.forInt(targets.length)); - emitCompare(crb, masm, keyValue, scratchValue, constVal); - masm.branchConditionally(AArch64Assembler.ConditionFlag.HS, defaultTarget.label()); + masm.branchConditionally(ConditionFlag.HI, defaultTarget.label()); } - // Load the start address of the jump table - which starts 3 instructions after the adr - // - into scratch. - masm.adr(scratch, 4 * 3); - masm.ldr(32, scratch, AArch64Address.createRegisterOffsetAddress(scratch, key, /* scaled */true)); - masm.jmp(scratch); - int jumpTablePos = masm.position(); + Label jumpTable = new Label(); + masm.adr(scratchReg, jumpTable); + masm.add(64, scratchReg, scratchReg, idxScratchReg, ExtendType.UXTW, 2); + masm.jmp(scratchReg); + masm.bind(jumpTable); // emit jump table entries for (LabelRef target : targets) { - Label label = target.label(); - if (label.isBound()) { - masm.emitInt(target.label().position()); - } else { - label.addPatchAt(masm.position()); - masm.emitInt(PatchLabelKind.JUMP_ADDRESS.encoding); - } + masm.jmp(target.label()); } - JumpTable jt = new JumpTable(jumpTablePos, lowKey, lowKey + targets.length - 1, 4); + JumpTable jt = new JumpTable(jumpTable.position(), lowKey, highKey - 1, 4); crb.compilationResult.addAnnotation(jt); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java index 0fb4e831102..d6349aeda43 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java @@ -110,6 +110,7 @@ public class AArch64Move { super(TYPE); this.result = result; this.input = input; + assert !(isStackSlot(result) && isStackSlot(input)); } @Override @@ -144,7 +145,7 @@ public class AArch64Move { public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register dst = asRegister(result); AArch64Address adr = address.toAddress(); - masm.loadAddress(dst, adr, address.getPlatformKind().getSizeInBytes()); + masm.loadAddress(dst, adr, address.getScaleFactor()); } } @@ -182,9 +183,11 @@ public class AArch64Move { @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - AArch64Address address = (AArch64Address) crb.asAddress(slot); - PlatformKind kind = AArch64Kind.QWORD; - masm.loadAddress(asRegister(result, kind), address, kind.getSizeInBytes()); + try (ScratchRegister addrReg = masm.getScratchRegister()) { + AArch64Address address = loadStackSlotAddress(crb, masm, (StackSlot) slot, addrReg.getRegister()); + PlatformKind kind = AArch64Kind.QWORD; + masm.loadAddress(asRegister(result, kind), address, kind.getSizeInBytes()); + } } } @@ -238,8 +241,8 @@ public class AArch64Move { @Override public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { - int immediate = addressValue.getImmediate(); - if (state == null && value.equals(addressValue.getBase()) && addressValue.getOffset().equals(Value.ILLEGAL) && immediate >= 0 && immediate < implicitNullCheckLimit) { + int displacement = addressValue.getDisplacement(); + if (state == null && value.equals(addressValue.getBase()) && addressValue.getOffset().equals(Value.ILLEGAL) && displacement >= 0 && displacement < implicitNullCheckLimit) { state = nullCheckState; return true; } @@ -265,8 +268,7 @@ public class AArch64Move { int destSize = result.getPlatformKind().getSizeInBytes() * Byte.SIZE; int srcSize = kind.getSizeInBytes() * Byte.SIZE; if (kind.isInteger()) { - // TODO How to load unsigned chars without the necessary information? - masm.ldrs(destSize, srcSize, dst, address); + masm.ldr(srcSize, dst, address); } else { assert srcSize == destSize; masm.fldr(srcSize, dst, address); @@ -412,6 +414,8 @@ public class AArch64Move { } else if (isStackSlot(input)) { if (isRegister(result)) { stack2reg(crb, masm, result, asAllocatableValue(input)); + } else if (isStackSlot(result)) { + emitStackMove(crb, masm, result, input); } else { throw GraalError.shouldNotReachHere(); } @@ -426,6 +430,25 @@ public class AArch64Move { } } + private static void emitStackMove(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, Value input) { + try (ScratchRegister r1 = masm.getScratchRegister()) { + try (ScratchRegister r2 = masm.getScratchRegister()) { + Register rscratch1 = r1.getRegister(); + Register rscratch2 = r2.getRegister(); + // use the slot kind to define the operand size + PlatformKind kind = input.getPlatformKind(); + final int size = kind.getSizeInBytes() * Byte.SIZE; + + // Always perform stack -> stack copies through integer registers + crb.blockComment("[stack -> stack copy]"); + AArch64Address src = loadStackSlotAddress(crb, masm, asStackSlot(input), rscratch2); + masm.ldr(size, rscratch1, src); + AArch64Address dst = loadStackSlotAddress(crb, masm, asStackSlot(result), rscratch2); + masm.str(size, rscratch1, dst); + } + } + } + private static void reg2reg(@SuppressWarnings("unused") CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, AllocatableValue input) { Register dst = asRegister(result); Register src = asRegister(input); @@ -444,8 +467,9 @@ public class AArch64Move { private static void reg2stack(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, AllocatableValue input) { AArch64Address dest = loadStackSlotAddress(crb, masm, asStackSlot(result), Value.ILLEGAL); Register src = asRegister(input); - AArch64Kind kind = (AArch64Kind) input.getPlatformKind(); - int size = kind.getSizeInBytes() * Byte.SIZE; + // use the slot kind to define the operand size + AArch64Kind kind = (AArch64Kind) result.getPlatformKind(); + final int size = kind.getSizeInBytes() * Byte.SIZE; if (kind.isInteger()) { masm.str(size, src, dest); } else { @@ -455,6 +479,7 @@ public class AArch64Move { private static void stack2reg(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, AllocatableValue input) { AArch64Kind kind = (AArch64Kind) input.getPlatformKind(); + // use the slot kind to define the operand size final int size = kind.getSizeInBytes() * Byte.SIZE; if (kind.isInteger()) { AArch64Address src = loadStackSlotAddress(crb, masm, asStackSlot(input), result); @@ -524,15 +549,17 @@ public class AArch64Move { } private static void const2stack(CompilationResultBuilder crb, AArch64MacroAssembler masm, Value result, JavaConstant constant) { - if (constant.isDefaultForKind() || constant.isNull()) { - AArch64Address resultAddress = (AArch64Address) crb.asAddress(result); - emitStore(crb, masm, (AArch64Kind) result.getPlatformKind(), resultAddress, zr.asValue(LIRKind.combine(result))); - } else { - try (ScratchRegister sc = masm.getScratchRegister()) { - Value scratchRegisterValue = sc.getRegister().asValue(LIRKind.combine(result)); - const2reg(crb, masm, scratchRegisterValue, constant); - AArch64Address resultAddress = (AArch64Address) crb.asAddress(result); - emitStore(crb, masm, (AArch64Kind) result.getPlatformKind(), resultAddress, scratchRegisterValue); + try (ScratchRegister addrReg = masm.getScratchRegister()) { + StackSlot slot = (StackSlot) result; + AArch64Address resultAddress = loadStackSlotAddress(crb, masm, slot, addrReg.getRegister()); + if (constant.isDefaultForKind() || constant.isNull()) { + emitStore(crb, masm, (AArch64Kind) result.getPlatformKind(), resultAddress, zr.asValue(LIRKind.combine(result))); + } else { + try (ScratchRegister sc = masm.getScratchRegister()) { + Value scratchRegisterValue = sc.getRegister().asValue(LIRKind.combine(result)); + const2reg(crb, masm, scratchRegisterValue, constant); + emitStore(crb, masm, (AArch64Kind) result.getPlatformKind(), resultAddress, scratchRegisterValue); + } } } } @@ -552,9 +579,13 @@ public class AArch64Move { * @return AArch64Address of given StackSlot. Uses scratch register if necessary to do so. */ private static AArch64Address loadStackSlotAddress(CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot slot, AllocatableValue scratch) { + Register scratchReg = Value.ILLEGAL.equals(scratch) ? zr : asRegister(scratch); + return loadStackSlotAddress(crb, masm, slot, scratchReg); + } + + private static AArch64Address loadStackSlotAddress(CompilationResultBuilder crb, AArch64MacroAssembler masm, StackSlot slot, Register scratchReg) { int displacement = crb.frameMap.offsetForStackSlot(slot); int transferSize = slot.getPlatformKind().getSizeInBytes(); - Register scratchReg = Value.ILLEGAL.equals(scratch) ? zr : asRegister(scratch); return masm.makeAddress(sp, displacement, scratchReg, transferSize, /* allowOverwrite */false); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64PrefetchOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64PrefetchOp.java index 814c32c1165..35c07ad8ce3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64PrefetchOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64PrefetchOp.java @@ -25,6 +25,7 @@ package org.graalvm.compiler.lir.aarch64; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; +import org.graalvm.compiler.asm.aarch64.AArch64Assembler.PrefetchMode; import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; @@ -32,18 +33,18 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder; public final class AArch64PrefetchOp extends AArch64LIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AArch64PrefetchOp.class); - @SuppressWarnings("unused") private final int instr; // AllocatePrefetchInstr + private final PrefetchMode mode; // AllocatePrefetchInstr @Alive({COMPOSITE}) protected AArch64AddressValue address; - public AArch64PrefetchOp(AArch64AddressValue address, int instr) { + public AArch64PrefetchOp(AArch64AddressValue address, PrefetchMode mode) { super(TYPE); this.address = address; - this.instr = instr; + this.mode = mode; } @Override public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { - // TODO implement prefetch - masm.nop(); + // instr gets ignored! + masm.prfm(address.toAddress(), mode); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SignExtendOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SignExtendOp.java index 47f4d99ca91..49a7b278757 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SignExtendOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64SignExtendOp.java @@ -54,6 +54,6 @@ public class AArch64SignExtendOp extends AArch64LIRInstruction { public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { Register result = asRegister(resultValue); Register input = asRegister(inputValue); - masm.sxt(toBits, fromBits, result, input); + masm.sxt(toBits <= 32 ? 32 : 64, fromBits, result, input); } } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java new file mode 100644 index 00000000000..a5af104860c --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.aarch64; + +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; + +import org.graalvm.compiler.asm.aarch64.AArch64Address; +import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler; +import org.graalvm.compiler.lir.LIRFrameState; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.StandardOp.ImplicitNullCheck; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.code.Register; +import jdk.vm.ci.meta.AllocatableValue; +import jdk.vm.ci.meta.Value; + +/** + * AARCH64 LIR instructions that have one input and one output. + */ +public class AArch64Unary { + + /** + * Instruction with a {@link AArch64AddressValue memory} operand. + */ + public static class MemoryOp extends AArch64LIRInstruction implements ImplicitNullCheck { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(MemoryOp.class); + + private final boolean isSigned; + + @Def({REG}) protected AllocatableValue result; + @Use({COMPOSITE}) protected AArch64AddressValue input; + + @State protected LIRFrameState state; + + private int targetSize; + private int srcSize; + + public MemoryOp(boolean isSigned, int targetSize, int srcSize, AllocatableValue result, AArch64AddressValue input, LIRFrameState state) { + super(TYPE); + this.targetSize = targetSize; + this.srcSize = srcSize; + this.isSigned = isSigned; + this.result = result; + this.input = input; + this.state = state; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) { + if (state != null) { + crb.recordImplicitException(masm.position(), state); + } + AArch64Address address = input.toAddress(); + Register dst = asRegister(result); + if (isSigned) { + masm.ldrs(targetSize, srcSize, dst, address); + } else { + masm.ldr(srcSize, dst, address); + } + } + + @Override + public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) { + int displacement = input.getDisplacement(); + if (state == null && value.equals(input.getBase()) && input.getOffset().equals(Value.ILLEGAL) && displacement >= 0 && displacement < implicitNullCheckLimit) { + state = nullCheckState; + return true; + } + return false; + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64AddressValue.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64AddressValue.java index d67920fb023..f3f8a92f6a6 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64AddressValue.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64AddressValue.java @@ -65,6 +65,14 @@ public final class AMD64AddressValue extends CompositeValue { assert scale != null; } + public AllocatableValue getBase() { + return base; + } + + public AllocatableValue getIndex() { + return index; + } + @Override public CompositeValue forEachComponent(LIRInstruction inst, OperandMode mode, InstructionValueProcedure proc) { AllocatableValue newBase = (AllocatableValue) proc.doValue(inst, base, mode, flags); @@ -81,6 +89,10 @@ public final class AMD64AddressValue extends CompositeValue { proc.visitValue(inst, index, mode, flags); } + public AMD64AddressValue withKind(ValueKind newKind) { + return new AMD64AddressValue(newKind, base, index, scale, displacement); + } + private static Register toRegister(AllocatableValue value) { if (value.equals(Value.ILLEGAL)) { return Register.None; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java index cff91a19bac..d5419f74c30 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Binary.java @@ -32,7 +32,7 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.code.ValueUtil.isStackSlot; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java index 8669c5217de..5f8f04abc2b 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BinaryConsumer.java @@ -30,7 +30,7 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.code.ValueUtil.isStackSlot; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BlockEndOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BlockEndOp.java index 4f09ee0292d..def894caee8 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BlockEndOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64BlockEndOp.java @@ -23,11 +23,12 @@ package org.graalvm.compiler.lir.amd64; import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.StandardOp.AbstractBlockEndOp; +import org.graalvm.compiler.lir.StandardOp.BlockEndOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -public abstract class AMD64BlockEndOp extends AbstractBlockEndOp { +public abstract class AMD64BlockEndOp extends LIRInstruction implements BlockEndOp { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64BlockEndOp.class); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java index dbddbcb191c..41cf3c9a6f3 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java @@ -31,7 +31,7 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Address.Scale; import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag; @@ -110,6 +110,8 @@ public class AMD64ControlFlow { @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + boolean isNegated = false; + int jccPos = masm.position(); /* * The strategy for emitting jumps is: If either trueDestination or falseDestination is * the successor block, assume the block scheduler did the correct thing and jcc to the @@ -120,15 +122,18 @@ public class AMD64ControlFlow { */ if (crb.isSuccessorEdge(trueDestination)) { jcc(masm, true, falseDestination); + isNegated = true; } else if (crb.isSuccessorEdge(falseDestination)) { jcc(masm, false, trueDestination); } else if (trueDestinationProbability < 0.5) { jcc(masm, true, falseDestination); masm.jmp(trueDestination.label()); + isNegated = true; } else { jcc(masm, false, trueDestination); masm.jmp(falseDestination.label()); } + crb.recordBranch(jccPos, isNegated); } protected void jcc(AMD64MacroAssembler masm, boolean negate, LabelRef target) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java index 67bcfe63357..174305a29ec 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java @@ -24,7 +24,7 @@ package org.graalvm.compiler.lir.amd64; import static jdk.vm.ci.code.ValueUtil.asStackSlot; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.core.common.LIRKind; import org.graalvm.compiler.lir.framemap.FrameMap; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java index e2bdfd3f4df..8f5785159a1 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java @@ -35,7 +35,7 @@ import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.code.ValueUtil.isStackSlot; -import org.graalvm.compiler.asm.NumUtil; +import org.graalvm.compiler.core.common.NumUtil; import org.graalvm.compiler.asm.amd64.AMD64Address; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp; import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp; @@ -669,6 +669,28 @@ public class AMD64Move { } } + public static boolean canMoveConst2Stack(JavaConstant input) { + switch (input.getJavaKind().getStackKind()) { + case Int: + break; + case Long: + break; + case Float: + break; + case Double: + break; + case Object: + if (input.isNull()) { + return true; + } else { + return false; + } + default: + return false; + } + return true; + } + public static void const2stack(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, JavaConstant input) { AMD64Address dest = (AMD64Address) crb.asAddress(result); final long imm; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java index f4758ce3d31..68e80e0a95a 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java @@ -27,8 +27,6 @@ import static jdk.vm.ci.code.ValueUtil.asStackSlot; import static jdk.vm.ci.code.ValueUtil.isStackSlot; import java.util.Arrays; -import java.util.Set; - import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.LIRValueUtil; @@ -36,6 +34,7 @@ import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMap; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Register; @@ -61,16 +60,16 @@ public class AMD64SaveRegistersOp extends AMD64LIRInstruction implements SaveReg @Def(STACK) protected final AllocatableValue[] slots; /** - * Specifies if {@link #remove(Set)} should have an effect. + * Specifies if {@link #remove(EconomicSet)} should have an effect. */ protected final boolean supportsRemove; /** * * @param savedRegisters the registers saved by this operation which may be subject to - * {@linkplain #remove(Set) pruning} + * {@linkplain #remove(EconomicSet) pruning} * @param savedRegisterLocations the slots to which the registers are saved - * @param supportsRemove determines if registers can be {@linkplain #remove(Set) pruned} + * @param supportsRemove determines if registers can be {@linkplain #remove(EconomicSet) pruned} */ public AMD64SaveRegistersOp(Register[] savedRegisters, AllocatableValue[] savedRegisterLocations, boolean supportsRemove) { this(TYPE, savedRegisters, savedRegisterLocations, supportsRemove); @@ -108,14 +107,14 @@ public class AMD64SaveRegistersOp extends AMD64LIRInstruction implements SaveReg } @Override - public int remove(Set doNotSave) { + public int remove(EconomicSet doNotSave) { if (!supportsRemove) { throw new UnsupportedOperationException(); } return prune(doNotSave, savedRegisters); } - static int prune(Set toRemove, Register[] registers) { + static int prune(EconomicSet toRemove, Register[] registers) { int pruned = 0; for (int i = 0; i < registers.length; i++) { if (registers[i] != null) { diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringIndexOfOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringIndexOfOp.java new file mode 100644 index 00000000000..aeb736b5588 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringIndexOfOp.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.amd64; + +import static jdk.vm.ci.amd64.AMD64.rax; +import static jdk.vm.ci.amd64.AMD64.rcx; +import static jdk.vm.ci.amd64.AMD64.rdx; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; + +import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.compiler.lir.gen.LIRGeneratorTool; + +import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.amd64.AMD64.CPUFeature; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.RegisterValue; +import jdk.vm.ci.meta.Value; + +/** + */ +@Opcode("AMD64_STRING_INDEX_OF") +public final class AMD64StringIndexOfOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64StringIndexOfOp.class); + + @Def({REG}) protected Value resultValue; + @Alive({REG}) protected Value charPtr1Value; + @Alive({REG}) protected Value charPtr2Value; + @Use({REG}) protected RegisterValue cnt1Value; + @Temp({REG}) protected RegisterValue cnt1ValueT; + @Use({REG}) protected RegisterValue cnt2Value; + @Temp({REG}) protected RegisterValue cnt2ValueT; + @Temp({REG}) protected Value temp1; + @Temp({REG, ILLEGAL}) protected Value vectorTemp1; + + private final int intCnt2; + + private final int vmPageSize; + + public AMD64StringIndexOfOp(LIRGeneratorTool tool, Value result, Value charPtr1, Value charPtr2, RegisterValue cnt1, RegisterValue cnt2, RegisterValue temp1, RegisterValue vectorTemp1, + int intCnt2, int vmPageSize) { + super(TYPE); + assert ((AMD64) tool.target().arch).getFeatures().contains(CPUFeature.SSE4_2); + resultValue = result; + charPtr1Value = charPtr1; + charPtr2Value = charPtr2; + /* + * The count values are inputs but are also killed like temporaries so need both Use and + * Temp annotations, which will only work with fixed registers. + */ + cnt1Value = cnt1; + cnt1ValueT = cnt1; + cnt2Value = cnt2; + cnt2ValueT = cnt2; + assert asRegister(cnt1).equals(rdx) && asRegister(cnt2).equals(rax) && asRegister(temp1).equals(rcx) : "fixed register usage required"; + + this.temp1 = temp1; + this.vectorTemp1 = vectorTemp1; + this.intCnt2 = intCnt2; + this.vmPageSize = vmPageSize; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + Register charPtr1 = asRegister(charPtr1Value); + Register charPtr2 = asRegister(charPtr2Value); + Register cnt1 = asRegister(cnt1Value); + Register cnt2 = asRegister(cnt2Value); + Register result = asRegister(resultValue); + Register vec = asRegister(vectorTemp1); + Register tmp = asRegister(temp1); + if (intCnt2 >= 8) { + masm.stringIndexofC8(charPtr1, charPtr2, cnt1, cnt2, intCnt2, result, vec, tmp); + } else { + masm.stringIndexOf(charPtr1, charPtr2, cnt1, cnt2, intCnt2, result, vec, tmp, vmPageSize); + } + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java index 1345b49e2e2..134abcbb7ec 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java @@ -24,14 +24,13 @@ package org.graalvm.compiler.lir.amd64; import static org.graalvm.compiler.lir.amd64.AMD64SaveRegistersOp.prune; -import java.util.Set; - import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.Opcode; import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.framemap.FrameMap; +import org.graalvm.util.EconomicSet; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterSaveLayout; @@ -76,7 +75,7 @@ public final class AMD64ZapRegistersOp extends AMD64LIRInstruction implements Sa } @Override - public int remove(Set doNotSave) { + public int remove(EconomicSet doNotSave) { return prune(doNotSave, zappedRegisters); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java index 3eee2c46aa3..74cf8fabfca 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java @@ -29,8 +29,8 @@ import java.util.Collections; import java.util.List; import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; -import org.graalvm.compiler.debug.Debug; -import org.graalvm.compiler.debug.DebugCounter; +import org.graalvm.compiler.debug.CounterKey; +import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.lir.LIR; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.RedundantMoveElimination; @@ -38,7 +38,7 @@ import org.graalvm.compiler.lir.amd64.AMD64Move.AMD64MultiStackMove; import org.graalvm.compiler.lir.amd64.AMD64Move.AMD64StackMove; import org.graalvm.compiler.lir.gen.LIRGenerationResult; import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase; -import org.graalvm.compiler.options.NestedBooleanOptionValue; +import org.graalvm.compiler.options.NestedBooleanOptionKey; import org.graalvm.compiler.options.Option; import org.graalvm.compiler.options.OptionType; @@ -58,18 +58,19 @@ public class StackMoveOptimizationPhase extends PostAllocationOptimizationPhase public static class Options { // @formatter:off @Option(help = "", type = OptionType.Debug) - public static final NestedBooleanOptionValue LIROptStackMoveOptimizer = new NestedBooleanOptionValue(LIROptimization, true); + public static final NestedBooleanOptionKey LIROptStackMoveOptimizer = new NestedBooleanOptionKey(LIROptimization, true); // @formatter:on } - private static final DebugCounter eliminatedBackup = Debug.counter("StackMoveOptimizer[EliminatedScratchBackupRestore]"); + private static final CounterKey eliminatedBackup = DebugContext.counter("StackMoveOptimizer[EliminatedScratchBackupRestore]"); @Override protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PostAllocationOptimizationContext context) { LIR lir = lirGenRes.getLIR(); + DebugContext debug = lir.getDebug(); for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { - List instructions = lir.getLIRforBlock(block); - new Closure().process(instructions); + ArrayList instructions = lir.getLIRforBlock(block); + new Closure().process(debug, instructions); } } @@ -83,7 +84,7 @@ public class StackMoveOptimizationPhase extends PostAllocationOptimizationPhase private AllocatableValue slot; private boolean removed = false; - public void process(List instructions) { + public void process(DebugContext debug, List instructions) { for (int i = 0; i < instructions.size(); i++) { LIRInstruction inst = instructions.get(i); @@ -92,7 +93,7 @@ public class StackMoveOptimizationPhase extends PostAllocationOptimizationPhase if (reg != null && !reg.equals(move.getScratchRegister())) { // end of trace & start of new - replaceStackMoves(instructions); + replaceStackMoves(debug, instructions); } // lazy initialize @@ -114,7 +115,7 @@ public class StackMoveOptimizationPhase extends PostAllocationOptimizationPhase } else if (begin != NONE) { // end of trace - replaceStackMoves(instructions); + replaceStackMoves(debug, instructions); } } // remove instructions @@ -124,7 +125,7 @@ public class StackMoveOptimizationPhase extends PostAllocationOptimizationPhase } - private void replaceStackMoves(List instructions) { + private void replaceStackMoves(DebugContext debug, List instructions) { int size = dst.size(); if (size > 1) { AMD64MultiStackMove multiMove = new AMD64MultiStackMove(dst.toArray(new AllocatableValue[size]), src.toArray(new AllocatableValue[size]), reg, slot); @@ -134,7 +135,7 @@ public class StackMoveOptimizationPhase extends PostAllocationOptimizationPhase Collections.fill(instructions.subList(begin + 1, begin + size), null); // removed removed = true; - eliminatedBackup.add(size - 1); + eliminatedBackup.add(debug, size - 1); } // reset dst.clear(); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/LIRTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/LIRTest.java index 39e4c7f8c79..0a4e15e2481 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/LIRTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/LIRTest.java @@ -40,7 +40,6 @@ import org.graalvm.compiler.jtt.JTTTest; import org.graalvm.compiler.nodeinfo.NodeInfo; import org.graalvm.compiler.nodes.FixedWithNextNode; import org.graalvm.compiler.nodes.ValueNode; -import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; @@ -191,9 +190,7 @@ public abstract class LIRTest extends JTTTest { }; @Override - protected GraphBuilderConfiguration editGraphBuilderConfiguration(GraphBuilderConfiguration conf) { - InvocationPlugins invocationPlugins = conf.getPlugins().getInvocationPlugins(); - + protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) { Class c = getClass(); for (Method m : c.getMethods()) { if (m.getAnnotation(LIRIntrinsic.class) != null) { @@ -215,7 +212,7 @@ public abstract class LIRTest extends JTTTest { }; invocationPlugins.register(outputPlugin, LIRTest.class, "getOutput", new Class[]{LIRTestSpecification.class, String.class, Object.class}); invocationPlugins.register(outputPlugin, LIRTest.class, "getOutput", new Class[]{LIRTestSpecification.class, String.class, int.class}); - return super.editGraphBuilderConfiguration(conf); + super.registerInvocationPlugins(invocationPlugins); } @SuppressWarnings("unused") diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java index 2f6cc407e45..98c5534860d 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/SPARCBranchBailoutTest.java @@ -22,17 +22,20 @@ */ package org.graalvm.compiler.lir.jtt; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Test; - import org.graalvm.compiler.api.directives.GraalDirectives; -import org.graalvm.compiler.common.PermanentBailoutException; +import org.graalvm.compiler.core.common.PermanentBailoutException; +import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.debug.DebugContext.Scope; import org.graalvm.compiler.debug.GraalError; import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; +import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Test; import jdk.vm.ci.code.BailoutException; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -76,12 +79,17 @@ public class SPARCBranchBailoutTest extends LIRTest { return GraalDirectives.opaque(res); } + @SuppressWarnings("try") @Test public void testBailoutOnBranchOverflow() throws Throwable { Assume.assumeTrue(getBackend().getTarget().arch instanceof SPARC); ResolvedJavaMethod m = getResolvedJavaMethod("testBranch"); + DebugContext debug = getDebugContext(); try { - compile(m, null); + try (Scope s = debug.disable()) { + StructuredGraph graph = parseEager(m, AllowAssumptions.YES, debug); + compile(m, graph); + } } catch (GraalError e) { Assert.assertEquals(PermanentBailoutException.class, e.getCause().getClass()); } diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/StackStoreLoadTest.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/StackStoreLoadTest.java new file mode 100644 index 00000000000..a11a501e1d0 --- /dev/null +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/StackStoreLoadTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, Red Hat Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.lir.jtt; + +import org.junit.Before; +import org.junit.Test; + +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.lir.Variable; +import org.graalvm.compiler.lir.VirtualStackSlot; +import org.graalvm.compiler.lir.framemap.FrameMapBuilder; +import org.graalvm.compiler.lir.gen.LIRGeneratorTool; + +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.PlatformKind; +import jdk.vm.ci.meta.Value; +import jdk.vm.ci.meta.ValueKind; + +public class StackStoreLoadTest extends LIRTest { + private static PlatformKind byteKind; + private static PlatformKind shortKind; + + @Before + public void setUp() { + byteKind = getBackend().getTarget().arch.getPlatformKind(JavaKind.Byte); + shortKind = getBackend().getTarget().arch.getPlatformKind(JavaKind.Short); + } + + private static class StackStoreLoadSpec extends LIRTestSpecification { + @Override + public void generate(LIRGeneratorTool gen, Value a) { + FrameMapBuilder frameMapBuilder = gen.getResult().getFrameMapBuilder(); + ValueKind valueKind = getValueKind(a); + + // create slots + VirtualStackSlot s1 = frameMapBuilder.allocateSpillSlot(valueKind); + VirtualStackSlot s2 = frameMapBuilder.allocateSpillSlot(valueKind); + VirtualStackSlot s3 = frameMapBuilder.allocateSpillSlot(valueKind); + + // start emit + gen.emitMove(s1, a); + gen.emitMove(s2, a); + gen.emitMove(s3, a); + gen.append(gen.getSpillMoveFactory().createStackMove(s1, s3)); + Variable result = gen.emitMove(s2); + Value slot1 = gen.emitMove(s1); + Value slot3 = gen.emitMove(s3); + // end emit + + // set output and result + setResult(result); + setOutput("slot1", slot1); + setOutput("slot3", slot3); + } + + protected ValueKind getValueKind(Value value) { + return value.getValueKind(); + } + } + + /* + * short + */ + + private static final LIRTestSpecification shortStackCopy = new StackStoreLoadSpec() { + @Override + protected ValueKind getValueKind(Value value) { + return LIRKind.value(shortKind); + } + }; + + @SuppressWarnings("unused") + @LIRIntrinsic + public static short copyShort(LIRTestSpecification spec, short a) { + return a; + } + + public short[] testShort(short a, short[] out) { + out[0] = copyShort(shortStackCopy, a); + out[1] = getOutput(shortStackCopy, "slot1", a); + out[2] = getOutput(shortStackCopy, "slot3", a); + return out; + } + + @Test + public void runShort() throws Throwable { + runTest("testShort", Short.MIN_VALUE, supply(() -> new short[3])); + runTest("testShort", (short) -1, supply(() -> new short[3])); + runTest("testShort", (short) 0, supply(() -> new short[3])); + runTest("testShort", (short) 1, supply(() -> new short[3])); + runTest("testShort", Short.MAX_VALUE, supply(() -> new short[3])); + } + + /* + * byte + */ + + private static final LIRTestSpecification byteStackCopy = new StackStoreLoadSpec() { + @Override + protected ValueKind getValueKind(Value value) { + return LIRKind.value(byteKind); + } + }; + + @SuppressWarnings("unused") + @LIRIntrinsic + public static byte copyByte(LIRTestSpecification spec, byte a) { + return a; + } + + public byte[] testByte(byte a, byte[] out) { + out[0] = copyByte(byteStackCopy, a); + out[1] = getOutput(byteStackCopy, "slot1", a); + out[2] = getOutput(byteStackCopy, "slot3", a); + return out; + } + + @Test + public void runByte() throws Throwable { + runTest("testByte", Byte.MIN_VALUE, supply(() -> new byte[3])); + runTest("testByte", (byte) -1, supply(() -> new byte[3])); + runTest("testByte", (byte) 0, supply(() -> new byte[3])); + runTest("testByte", (byte) 1, supply(() -> new byte[3])); + runTest("testByte", Byte.MAX_VALUE, supply(() -> new byte[3])); + } +} diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArithmetic.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArithmetic.java index 44edf5a51c4..97b85ccd987 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArithmetic.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArithmetic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -71,7 +71,7 @@ public class SPARCArithmetic { public static final SizeEstimate SIZE = SizeEstimate.create(5); @Opcode private final FloatConvert opcode; - @Def({REG, HINT}) protected Value result; + @Def({REG, HINT}) protected AllocatableValue result; @Use({REG}) protected Value x; public enum FloatConvert { @@ -81,7 +81,7 @@ public class SPARCArithmetic { D2L } - public FloatConvertOp(FloatConvert opcode, Value x, Value result) { + public FloatConvertOp(FloatConvert opcode, Value x, AllocatableValue result) { super(TYPE, SIZE); this.opcode = opcode; this.x = x; @@ -138,11 +138,11 @@ public class SPARCArithmetic { public static final SizeEstimate SIZE = SizeEstimate.create(4); @Opcode private final Rem opcode; - @Def({REG}) protected Value result; + @Def({REG}) protected AllocatableValue result; @Alive({REG, CONST}) protected Value x; @Alive({REG, CONST}) protected Value y; - @Temp({REG}) protected Value scratch1; - @Temp({REG}) protected Value scratch2; + @Temp({REG}) protected AllocatableValue scratch1; + @Temp({REG}) protected AllocatableValue scratch2; @State protected LIRFrameState state; public enum Rem { @@ -150,7 +150,7 @@ public class SPARCArithmetic { LUREM } - public RemOp(Rem opcode, Value result, Value x, Value y, Value scratch1, Value scratch2, LIRFrameState state) { + public RemOp(Rem opcode, AllocatableValue result, Value x, Value y, AllocatableValue scratch1, AllocatableValue scratch2, LIRFrameState state) { super(TYPE, SIZE); this.opcode = opcode; this.result = result; @@ -170,7 +170,9 @@ public class SPARCArithmetic { assert !y.equals(scratch1); switch (opcode) { case LUREM: - crb.recordImplicitException(masm.position(), state); + if (state != null) { + crb.recordImplicitException(masm.position(), state); + } masm.udivx(asRegister(x, XWORD), crb.asIntConst(y), asRegister(scratch1, XWORD)); masm.mulx(asRegister(scratch1, XWORD), crb.asIntConst(y), asRegister(scratch2, XWORD)); getDelayedControlTransfer().emitControlTransfer(crb, masm); @@ -192,7 +194,9 @@ public class SPARCArithmetic { } assert !asRegister(xLeft, XWORD).equals(asRegister(scratch1, XWORD)); assert !asRegister(y, XWORD).equals(asRegister(scratch1, XWORD)); - crb.recordImplicitException(masm.position(), state); + if (state != null) { + crb.recordImplicitException(masm.position(), state); + } masm.udivx(asRegister(xLeft, XWORD), asRegister(y, XWORD), asRegister(scratch1, XWORD)); masm.mulx(asRegister(scratch1, XWORD), asRegister(y, XWORD), asRegister(scratch1, XWORD)); getDelayedControlTransfer().emitControlTransfer(crb, masm); @@ -203,7 +207,9 @@ public class SPARCArithmetic { assert !asRegister(result, WORD).equals(asRegister(scratch2, WORD)); masm.srl(asRegister(x, WORD), 0, asRegister(scratch1, WORD)); masm.srl(asRegister(y, WORD), 0, asRegister(result, WORD)); - crb.recordImplicitException(masm.position(), state); + if (state != null) { + crb.recordImplicitException(masm.position(), state); + } masm.udivx(asRegister(scratch1, WORD), asRegister(result, WORD), asRegister(scratch2, WORD)); masm.mulx(asRegister(scratch2, WORD), asRegister(result, WORD), asRegister(result, WORD)); getDelayedControlTransfer().emitControlTransfer(crb, masm); @@ -221,11 +227,11 @@ public class SPARCArithmetic { public static final class SPARCIMulccOp extends SPARCLIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCIMulccOp.class); public static final SizeEstimate SIZE = SizeEstimate.create(10); - @Def({REG}) protected Value result; - @Alive({REG}) protected Value x; - @Alive({REG}) protected Value y; + @Def({REG}) protected AllocatableValue result; + @Alive({REG}) protected AllocatableValue x; + @Alive({REG}) protected AllocatableValue y; - public SPARCIMulccOp(Value result, Value x, Value y) { + public SPARCIMulccOp(AllocatableValue result, AllocatableValue x, AllocatableValue y) { super(TYPE, SIZE); this.result = result; this.x = x; @@ -258,13 +264,13 @@ public class SPARCArithmetic { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCLMulccOp.class); public static final SizeEstimate SIZE = SizeEstimate.create(13); - @Def({REG}) protected Value result; - @Alive({REG}) protected Value x; - @Alive({REG}) protected Value y; - @Temp({REG}) protected Value scratch1; - @Temp({REG}) protected Value scratch2; + @Def({REG}) protected AllocatableValue result; + @Alive({REG}) protected AllocatableValue x; + @Alive({REG}) protected AllocatableValue y; + @Temp({REG}) protected AllocatableValue scratch1; + @Temp({REG}) protected AllocatableValue scratch2; - public SPARCLMulccOp(Value result, Value x, Value y, LIRGeneratorTool gen) { + public SPARCLMulccOp(AllocatableValue result, AllocatableValue x, AllocatableValue y, LIRGeneratorTool gen) { super(TYPE, SIZE); this.result = result; this.x = x; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java index 1a0be8840e5..78ef442a395 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCArrayEqualsOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -22,6 +22,9 @@ */ package org.graalvm.compiler.lir.sparc; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.sparc.SPARC.g0; +import static jdk.vm.ci.sparc.SPARCKind.WORD; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.ANNUL; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.Annul.NOT_ANNUL; @@ -32,9 +35,6 @@ import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.Equal; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.Less; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.ConditionFlag.NotEqual; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARC.g0; -import static jdk.vm.ci.sparc.SPARCKind.WORD; import java.lang.reflect.Array; import java.lang.reflect.Field; @@ -49,8 +49,8 @@ import org.graalvm.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import jdk.vm.ci.code.Register; +import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.Value; import jdk.vm.ci.sparc.SPARCKind; import sun.misc.Unsafe; @@ -66,17 +66,17 @@ public final class SPARCArrayEqualsOp extends SPARCLIRInstruction { private final int arrayBaseOffset; private final int arrayIndexScale; - @Def({REG}) protected Value resultValue; - @Alive({REG}) protected Value array1Value; - @Alive({REG}) protected Value array2Value; - @Alive({REG}) protected Value lengthValue; - @Temp({REG}) protected Value temp1; - @Temp({REG}) protected Value temp2; - @Temp({REG}) protected Value temp3; - @Temp({REG}) protected Value temp4; - @Temp({REG}) protected Value temp5; + @Def({REG}) protected AllocatableValue resultValue; + @Alive({REG}) protected AllocatableValue array1Value; + @Alive({REG}) protected AllocatableValue array2Value; + @Alive({REG}) protected AllocatableValue lengthValue; + @Temp({REG}) protected AllocatableValue temp1; + @Temp({REG}) protected AllocatableValue temp2; + @Temp({REG}) protected AllocatableValue temp3; + @Temp({REG}) protected AllocatableValue temp4; + @Temp({REG}) protected AllocatableValue temp5; - public SPARCArrayEqualsOp(LIRGeneratorTool tool, JavaKind kind, Value result, Value array1, Value array2, Value length) { + public SPARCArrayEqualsOp(LIRGeneratorTool tool, JavaKind kind, AllocatableValue result, AllocatableValue array1, AllocatableValue array2, AllocatableValue length) { super(TYPE, SIZE); this.kind = kind; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBitManipulationOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBitManipulationOp.java index 1221cebba46..e296e65396e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBitManipulationOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBitManipulationOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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 @@ -22,12 +22,12 @@ */ package org.graalvm.compiler.lir.sparc; -import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.vm.ci.code.ValueUtil.isRegister; import static jdk.vm.ci.sparc.SPARC.g0; import static jdk.vm.ci.sparc.SPARCKind.WORD; import static jdk.vm.ci.sparc.SPARCKind.XWORD; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; import org.graalvm.compiler.core.common.LIRKind; @@ -40,7 +40,6 @@ import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.PlatformKind; -import jdk.vm.ci.meta.Value; public final class SPARCBitManipulationOp extends SPARCLIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCBitManipulationOp.class); @@ -60,7 +59,7 @@ public final class SPARCBitManipulationOp extends SPARCLIRInstruction { @Opcode private final IntrinsicOpcode opcode; @Def protected AllocatableValue result; @Alive({REG}) protected AllocatableValue input; - @Temp({REG}) protected Value scratch; + @Temp({REG}) protected AllocatableValue scratch; public SPARCBitManipulationOp(IntrinsicOpcode opcode, AllocatableValue result, AllocatableValue input, LIRGeneratorTool gen) { super(TYPE, opcode.size); diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBlockEndOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBlockEndOp.java index ed551fce119..71617b952d0 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBlockEndOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCBlockEndOp.java @@ -23,11 +23,12 @@ package org.graalvm.compiler.lir.sparc; import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler; +import org.graalvm.compiler.lir.LIRInstruction; import org.graalvm.compiler.lir.LIRInstructionClass; -import org.graalvm.compiler.lir.StandardOp.AbstractBlockEndOp; +import org.graalvm.compiler.lir.StandardOp.BlockEndOp; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; -public abstract class SPARCBlockEndOp extends AbstractBlockEndOp implements SPARCLIRInstructionMixin { +public abstract class SPARCBlockEndOp extends LIRInstruction implements BlockEndOp, SPARCLIRInstructionMixin { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCBlockEndOp.class); private final SPARCLIRInstructionMixinStore store; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCByteSwapOp.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCByteSwapOp.java index 4679dacc6c1..e497ef90232 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCByteSwapOp.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCByteSwapOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -22,13 +22,13 @@ */ package org.graalvm.compiler.lir.sparc; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.sparc.SPARCKind.WORD; +import static jdk.vm.ci.sparc.SPARCKind.XWORD; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK; import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.UNINITIALIZED; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARCKind.WORD; -import static jdk.vm.ci.sparc.SPARCKind.XWORD; import org.graalvm.compiler.asm.sparc.SPARCAddress; import org.graalvm.compiler.asm.sparc.SPARCAssembler.Asi; @@ -43,19 +43,18 @@ import org.graalvm.compiler.lir.gen.LIRGeneratorTool; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.ValueUtil; import jdk.vm.ci.meta.AllocatableValue; -import jdk.vm.ci.meta.Value; import jdk.vm.ci.sparc.SPARCKind; @Opcode("BSWAP") public final class SPARCByteSwapOp extends SPARCLIRInstruction implements SPARCTailDelayedLIRInstruction { public static final LIRInstructionClass TYPE = LIRInstructionClass.create(SPARCByteSwapOp.class); public static final SizeEstimate SIZE = SizeEstimate.create(3); - @Def({REG, HINT}) protected Value result; - @Use({REG}) protected Value input; - @Temp({REG}) protected Value tempIndex; + @Def({REG, HINT}) protected AllocatableValue result; + @Use({REG}) protected AllocatableValue input; + @Temp({REG}) protected AllocatableValue tempIndex; @Use({STACK, UNINITIALIZED}) protected AllocatableValue tmpSlot; - public SPARCByteSwapOp(LIRGeneratorTool tool, Value result, Value input) { + public SPARCByteSwapOp(LIRGeneratorTool tool, AllocatableValue result, AllocatableValue input) { super(TYPE, SIZE); this.result = result; this.input = input; diff --git a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java index a7823bb46ba..ec96b34ba4e 100644 --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2017, 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 @@ -22,6 +22,11 @@ */ package org.graalvm.compiler.lir.sparc; +import static jdk.vm.ci.code.ValueUtil.asRegister; +import static jdk.vm.ci.sparc.SPARC.CPU; +import static jdk.vm.ci.sparc.SPARC.g0; +import static jdk.vm.ci.sparc.SPARCKind.WORD; +import static jdk.vm.ci.sparc.SPARCKind.XWORD; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.BPCC; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.CBCOND; import static org.graalvm.compiler.asm.sparc.SPARCAssembler.FBPCC; @@ -68,22 +73,14 @@ import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue; import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant; import static org.graalvm.compiler.lir.sparc.SPARCMove.const2reg; import static org.graalvm.compiler.lir.sparc.SPARCOP3Op.emitOp3; -import static jdk.vm.ci.code.ValueUtil.asRegister; -import static jdk.vm.ci.sparc.SPARC.CPU; -import static jdk.vm.ci.sparc.SPARC.g0; -import static jdk.vm.ci.sparc.SPARCKind.WORD; -import static jdk.vm.ci.sparc.SPARCKind.XWORD; import java.util.ArrayList; import java.util.EnumSet; -import java.util.HashMap; import java.util.List; -import java.util.Map; import org.graalvm.compiler.asm.Assembler; import org.graalvm.compiler.asm.Assembler.LabelHint; import org.graalvm.compiler.asm.Label; -import org.graalvm.compiler.asm.NumUtil; import org.graalvm.compiler.asm.sparc.SPARCAssembler; import org.graalvm.compiler.asm.sparc.SPARCAssembler.BranchPredict; import org.graalvm.compiler.asm.sparc.SPARCAssembler.CC; @@ -101,6 +98,8 @@ import org.graalvm.compiler.lir.SwitchStrategy; import org.graalvm.compiler.lir.SwitchStrategy.BaseSwitchClosure; import org.graalvm.compiler.lir.Variable; import org.graalvm.compiler.lir.asm.CompilationResultBuilder; +import org.graalvm.util.EconomicMap; +import org.graalvm.util.Equivalence; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; @@ -144,7 +143,7 @@ public class SPARCControlFlow { public static final SizeEstimate SIZE = SizeEstimate.create(3); static final EnumSet SUPPORTED_KINDS = EnumSet.of(XWORD, WORD); - @Use({REG}) protected Value x; + @Use({REG}) protected AllocatableValue x; @Use({REG, CONST}) protected Value y; private ConditionFlag conditionFlag; protected final LabelRef trueDestination; @@ -157,8 +156,10 @@ public class SPARCControlFlow { private int delaySlotPosition = -1; private double trueDestinationProbability; - public CompareBranchOp(Value x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, SPARCKind kind, boolean unorderedIsTrue, double trueDestinationProbability) { + public CompareBranchOp(AllocatableValue x, Value y, Condition condition, LabelRef trueDestination, LabelRef falseDestination, SPARCKind kind, boolean unorderedIsTrue, + double trueDestinationProbability) { super(TYPE, SIZE); + assert x.getPlatformKind() == y.getPlatformKind() : String.format("PlatformKind of x must match PlatformKind of y. %s!=%s", x.getPlatformKind(), y.getPlatformKind()); this.x = x; this.y = y; this.trueDestination = trueDestination; @@ -250,6 +251,7 @@ public class SPARCControlFlow { * @return true if the branch could be emitted */ private boolean emitShortCompareBranch(CompilationResultBuilder crb, SPARCMacroAssembler masm) { + boolean isLong = kind == SPARCKind.XWORD; ConditionFlag actualConditionFlag = conditionFlag; Label actualTrueTarget = trueDestination.label(); Label actualFalseTarget = falseDestination.label(); @@ -274,7 +276,7 @@ public class SPARCControlFlow { actualFalseTarget = tmpTarget; } } - emitCBCond(masm, x, y, actualTrueTarget, actualConditionFlag); + emitCBCond(masm, x, y, actualTrueTarget, actualConditionFlag, isLong); if (needJump) { masm.jmp(actualFalseTarget); masm.nop(); @@ -282,16 +284,24 @@ public class SPARCControlFlow { return true; } - private void emitCBCond(SPARCMacroAssembler masm, Value actualX, Value actualY, Label actualTrueTarget, ConditionFlag cFlag) { + private static void emitCBCond(SPARCMacroAssembler masm, Value actualX, Value actualY, Label actualTrueTarget, ConditionFlag cFlag, boolean isLong) { PlatformKind xKind = actualX.getPlatformKind(); - boolean isLong = kind == SPARCKind.XWORD; + Register rs1 = asRegister(actualX, xKind); if (isJavaConstant(actualY)) { JavaConstant c = asJavaConstant(actualY); long constantY = c.isNull() ? 0 : c.asLong(); - assert NumUtil.isInt(constantY); - CBCOND.emit(masm, cFlag, isLong, asRegister(actualX, xKind), (int) constantY, actualTrueTarget); + try (ScratchRegister scratch = masm.getScratchRegister()) { + if (SPARCMacroAssembler.isSimm5(constantY)) { + CBCOND.emit(masm, cFlag, isLong, rs1, (int) constantY, actualTrueTarget); + } else { // !simm5 + Register rs2 = scratch.getRegister(); + masm.setx(constantY, rs2, false); + CBCOND.emit(masm, cFlag, isLong, rs1, rs2, actualTrueTarget); + } + } } else { - CBCOND.emit(masm, cFlag, isLong, asRegister(actualX, xKind), asRegister(actualY, xKind), actualTrueTarget); + Register rs2 = asRegister(actualY, xKind); + CBCOND.emit(masm, cFlag, isLong, rs1, rs2, actualTrueTarget); } } @@ -426,15 +436,16 @@ public class SPARCControlFlow { @Alive({REG, ILLEGAL}) protected Value constantTableBase; @Temp({REG}) protected Value scratch; protected final SwitchStrategy strategy; - private final Map labelHints; + private final EconomicMap labelHints; private final List