Merge
This commit is contained in:
commit
6b0b851a7c
3
.hgtags
3
.hgtags
@ -626,3 +626,6 @@ b2dd4028a6de4e40dda8b76109e4b5c6b294f980 jdk-15+11
|
||||
1d6ceb13e142665ea833fca01c8c8598e0ddd211 jdk-15+14
|
||||
bc54620a3848c26cff9766e5e2a6e5ddab98ed18 jdk-14-ga
|
||||
82b7c62cf4cc56828a8fb724f57087967232a2a7 jdk-15+15
|
||||
5c7ec21f5d13f6eb5cd32288c69b8be2f9cac256 jdk-15+16
|
||||
dd5198db2e5b1ebcafe065d987c03ba9fcb50fc3 jdk-15+17
|
||||
44aef192b488a48cce12422394691a6b1d16b98e jdk-15+18
|
||||
|
@ -283,7 +283,7 @@
|
||||
<tbody>
|
||||
<tr class="odd">
|
||||
<td style="text-align: left;">Linux</td>
|
||||
<td style="text-align: left;">gcc 8.3.0</td>
|
||||
<td style="text-align: left;">gcc 9.2.0</td>
|
||||
</tr>
|
||||
<tr class="even">
|
||||
<td style="text-align: left;">macOS</td>
|
||||
@ -302,7 +302,7 @@
|
||||
<p>All compilers are expected to be able to compile to the C99 language standard, as some C99 features are used in the source code. Microsoft Visual Studio doesn't fully support C99 so in practice shared code is limited to using C99 features that it does support.</p>
|
||||
<h3 id="gcc">gcc</h3>
|
||||
<p>The minimum accepted version of gcc is 5.0. Older versions will generate a warning by <code>configure</code> and are unlikely to work.</p>
|
||||
<p>The JDK is currently known to be able to compile with at least version 8.3 of gcc.</p>
|
||||
<p>The JDK is currently known to be able to compile with at least version 9.2 of gcc.</p>
|
||||
<p>In general, any version between these two should be usable.</p>
|
||||
<h3 id="clang">clang</h3>
|
||||
<p>The minimum accepted version of clang is 3.2. Older versions will not be accepted by <code>configure</code>.</p>
|
||||
|
@ -327,7 +327,7 @@ issues.
|
||||
|
||||
Operating system Toolchain version
|
||||
------------------ -------------------------------------------------------
|
||||
Linux gcc 8.3.0
|
||||
Linux gcc 9.2.0
|
||||
macOS Apple Xcode 10.1 (using clang 10.0.0)
|
||||
Solaris Oracle Solaris Studio 12.6 (with compiler version 5.15)
|
||||
Windows Microsoft Visual Studio 2017 update 15.9.16
|
||||
@ -342,7 +342,7 @@ features that it does support.
|
||||
The minimum accepted version of gcc is 5.0. Older versions will generate a warning
|
||||
by `configure` and are unlikely to work.
|
||||
|
||||
The JDK is currently known to be able to compile with at least version 8.3 of
|
||||
The JDK is currently known to be able to compile with at least version 9.2 of
|
||||
gcc.
|
||||
|
||||
In general, any version between these two should be usable.
|
||||
|
@ -351,11 +351,6 @@ jdk.scripting.nashorn.shell_COPY += .js .properties
|
||||
|
||||
################################################################################
|
||||
|
||||
jdk.rmic_DISABLED_WARNINGS += deprecation
|
||||
jdk.rmic_CLEAN += .properties
|
||||
|
||||
################################################################################
|
||||
|
||||
# No SCTP implementation on Mac OS X or AIX. These classes should be excluded.
|
||||
SCTP_IMPL_CLASSES = \
|
||||
$(TOPDIR)/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/AssociationChange.java \
|
||||
|
@ -43,7 +43,7 @@ BUILD_TOOLS_SRC_DIRS += \
|
||||
$(BUILDTOOLS_OUTPUTDIR)/interim_tzdb_classes \
|
||||
#
|
||||
|
||||
$(eval $(call SetupJavaCompilation,BUILD_TOOLS_JDK, \
|
||||
$(eval $(call SetupJavaCompilation, BUILD_TOOLS_JDK, \
|
||||
SETUP := GENERATE_OLDBYTECODE, \
|
||||
SRC := $(BUILD_TOOLS_SRC_DIRS), \
|
||||
EXCLUDES := \
|
||||
@ -53,7 +53,6 @@ $(eval $(call SetupJavaCompilation,BUILD_TOOLS_JDK, \
|
||||
build/tools/jigsaw \
|
||||
build/tools/depend \
|
||||
, \
|
||||
DISABLED_WARNINGS := unchecked rawtypes deprecation cast, \
|
||||
BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
|
||||
ADD_JAVAC_FLAGS := \
|
||||
--add-exports java.desktop/sun.awt=ALL-UNNAMED \
|
||||
|
@ -95,6 +95,9 @@ if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
export HOTSPOT_BUILD_TIME="@HOTSPOT_BUILD_TIME@"
|
||||
export USE_PRECOMPILED_HEADER="@USE_PRECOMPILED_HEADER@"
|
||||
|
||||
# Now locate the main script and run it.
|
||||
REAL_COMPARE_SCRIPT="$TOPDIR/make/scripts/compare.sh"
|
||||
if [ ! -e "$REAL_COMPARE_SCRIPT" ]; then
|
||||
|
@ -697,7 +697,10 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER],
|
||||
# JDK libraries.
|
||||
STATIC_LIBS_CFLAGS="-DSTATIC_BUILD=1"
|
||||
if test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then
|
||||
STATIC_LIBS_CFLAGS="$STATIC_LIBS_CFLAGS -ffunction-sections -fdata-sections"
|
||||
STATIC_LIBS_CFLAGS="$STATIC_LIBS_CFLAGS -ffunction-sections -fdata-sections \
|
||||
-DJNIEXPORT='__attribute__((visibility(\"hidden\")))'"
|
||||
else
|
||||
STATIC_LIBS_CFLAGS="$STATIC_LIBS_CFLAGS -DJNIEXPORT="
|
||||
fi
|
||||
if test "x$TOOLCHAIN_TYPE" = xgcc; then
|
||||
# Disable relax-relocation to enable compatibility with older linkers
|
||||
|
@ -69,9 +69,10 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER],
|
||||
LIBJSIG_HASHSTYLE_LDFLAGS="-Wl,--hash-style=both"
|
||||
fi
|
||||
|
||||
# Add -z defs, to forbid undefined symbols in object files.
|
||||
# add relro (mark relocations read only) for all libs
|
||||
BASIC_LDFLAGS="$BASIC_LDFLAGS -Wl,-z,defs -Wl,-z,relro"
|
||||
# Add -z,defs, to forbid undefined symbols in object files.
|
||||
# add -z,relro (mark relocations read only) for all libs
|
||||
# add -z,now ("full relro" - more of the Global Offset Table GOT is marked read only)
|
||||
BASIC_LDFLAGS="$BASIC_LDFLAGS -Wl,-z,defs -Wl,-z,relro -Wl,-z,now"
|
||||
# Linux : remove unused code+data in link step
|
||||
if test "x$ENABLE_LINKTIME_GC" = xtrue; then
|
||||
if test "x$OPENJDK_TARGET_CPU" = xs390x; then
|
||||
@ -129,10 +130,6 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER],
|
||||
if test x$DEBUG_LEVEL = xrelease; then
|
||||
DEBUGLEVEL_LDFLAGS_JDK_ONLY="$DEBUGLEVEL_LDFLAGS_JDK_ONLY -Wl,-O1"
|
||||
fi
|
||||
if test x$DEBUG_LEVEL = xslowdebug; then
|
||||
# do relocations at load
|
||||
DEBUGLEVEL_LDFLAGS="-Wl,-z,now"
|
||||
fi
|
||||
fi
|
||||
|
||||
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
|
||||
|
@ -157,6 +157,15 @@ AC_DEFUN_ONCE([HOTSPOT_SETUP_MISC],
|
||||
HOTSPOT_TARGET_CPU_ARCH=zero
|
||||
fi
|
||||
|
||||
AC_ARG_WITH([hotspot-build-time], [AS_HELP_STRING([--with-hotspot-build-time],
|
||||
[timestamp to use in hotspot version string, empty for on-the-fly @<:@empty@:>@])])
|
||||
|
||||
if test "x$with_hotspot_build_time" != x; then
|
||||
HOTSPOT_BUILD_TIME="$with_hotspot_build_time"
|
||||
fi
|
||||
AC_SUBST(HOTSPOT_BUILD_TIME)
|
||||
|
||||
|
||||
# Override hotspot cpu definitions for ARM platforms
|
||||
if test "x$OPENJDK_TARGET_CPU" = xarm; then
|
||||
HOTSPOT_TARGET_CPU=arm_32
|
||||
|
@ -120,6 +120,12 @@ AC_DEFUN([PLATFORM_EXTRACT_VARS_FROM_CPU],
|
||||
VAR_CPU_BITS=64
|
||||
VAR_CPU_ENDIAN=little
|
||||
;;
|
||||
riscv64)
|
||||
VAR_CPU=riscv64
|
||||
VAR_CPU_ARCH=riscv
|
||||
VAR_CPU_BITS=64
|
||||
VAR_CPU_ENDIAN=little
|
||||
;;
|
||||
s390)
|
||||
VAR_CPU=s390
|
||||
VAR_CPU_ARCH=s390
|
||||
@ -485,6 +491,8 @@ AC_DEFUN([PLATFORM_SETUP_LEGACY_VARS_HELPER],
|
||||
HOTSPOT_$1_CPU_DEFINE=S390
|
||||
elif test "x$OPENJDK_$1_CPU" = xs390x; then
|
||||
HOTSPOT_$1_CPU_DEFINE=S390
|
||||
elif test "x$OPENJDK_$1_CPU" = xriscv64; then
|
||||
HOTSPOT_$1_CPU_DEFINE=RISCV
|
||||
elif test "x$OPENJDK_$1_CPU" != x; then
|
||||
HOTSPOT_$1_CPU_DEFINE=$(echo $OPENJDK_$1_CPU | tr a-z A-Z)
|
||||
fi
|
||||
|
@ -156,6 +156,7 @@ IMPORT_MODULES_SRC:=@IMPORT_MODULES_SRC@
|
||||
IMPORT_MODULES_MAKE:=@IMPORT_MODULES_MAKE@
|
||||
|
||||
COPYRIGHT_YEAR:=@COPYRIGHT_YEAR@
|
||||
HOTSPOT_BUILD_TIME:=@HOTSPOT_BUILD_TIME@
|
||||
|
||||
# Platform naming variables
|
||||
LAUNCHER_NAME:=@LAUNCHER_NAME@
|
||||
@ -245,7 +246,7 @@ ifneq ($(COMPANY_NAME),)
|
||||
# Only export "VENDOR" to the build if COMPANY_NAME contains a real value.
|
||||
# Otherwise the default value for VENDOR, which is used to set the "java.vendor"
|
||||
# and "java.vm.vendor" properties is hard-coded into the source code (i.e. in
|
||||
# VersionProps.java.template in the jdk for "vm.vendor" and
|
||||
# VersionProps.java.template in the jdk for "java.vendor" and
|
||||
# vm_version.cpp in the VM for "java.vm.vendor")
|
||||
ifneq ($(COMPANY_NAME), N/A)
|
||||
VERSION_CFLAGS += -DVENDOR='"$(COMPANY_NAME)"'
|
||||
@ -761,7 +762,6 @@ OBJCOPY:=@OBJCOPY@
|
||||
SETFILE:=@SETFILE@
|
||||
XATTR:=@XATTR@
|
||||
JT_HOME:=@JT_HOME@
|
||||
JTREGEXE:=@JTREGEXE@
|
||||
JIB_HOME:=@JIB_HOME@
|
||||
XCODEBUILD=@XCODEBUILD@
|
||||
DTRACE := @DTRACE@
|
||||
|
@ -1092,15 +1092,10 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_JTREG],
|
||||
AC_MSG_ERROR([jtreg home directory from --with-jtreg=$with_jtreg is not a valid jtreg home])
|
||||
fi
|
||||
|
||||
JTREGEXE="$JT_HOME/bin/jtreg"
|
||||
if test ! -x "$JTREGEXE"; then
|
||||
AC_MSG_ERROR([jtreg home directory from --with-jtreg=$with_jtreg does not contain valid jtreg executable])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([for jtreg test harness])
|
||||
AC_MSG_RESULT([$JT_HOME])
|
||||
else
|
||||
# Try to locate jtreg
|
||||
# Try to locate jtreg using the JT_HOME environment variable
|
||||
if test "x$JT_HOME" != x; then
|
||||
# JT_HOME set in environment, use it
|
||||
if test ! -d "$JT_HOME"; then
|
||||
@ -1110,11 +1105,7 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_JTREG],
|
||||
if test ! -e "$JT_HOME/lib/jtreg.jar"; then
|
||||
AC_MSG_WARN([Ignoring JT_HOME which is not a valid jtreg home: $JT_HOME])
|
||||
JT_HOME=
|
||||
elif test ! -x "$JT_HOME/bin/jtreg"; then
|
||||
AC_MSG_WARN([Ignoring JT_HOME which does not contain valid jtreg executable: $JT_HOME])
|
||||
JT_HOME=
|
||||
else
|
||||
JTREGEXE="$JT_HOME/bin/jtreg"
|
||||
AC_MSG_NOTICE([Located jtreg using JT_HOME from environment])
|
||||
fi
|
||||
fi
|
||||
@ -1130,7 +1121,6 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_JTREG],
|
||||
if test ! -e "$JT_HOME/lib/jtreg.jar"; then
|
||||
AC_MSG_WARN([Ignoring jtreg from path since a valid jtreg home cannot be found])
|
||||
JT_HOME=
|
||||
JTREGEXE=
|
||||
else
|
||||
AC_MSG_NOTICE([Located jtreg using jtreg executable in path])
|
||||
fi
|
||||
@ -1149,10 +1139,8 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_JTREG],
|
||||
fi
|
||||
fi
|
||||
|
||||
UTIL_FIXUP_EXECUTABLE(JTREGEXE)
|
||||
UTIL_FIXUP_PATH(JT_HOME)
|
||||
AC_SUBST(JT_HOME)
|
||||
AC_SUBST(JTREGEXE)
|
||||
])
|
||||
|
||||
# Setup the JIB dependency resolver
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -171,7 +171,7 @@ DOCS_MODULES += \
|
||||
jdk.naming.dns \
|
||||
jdk.naming.rmi \
|
||||
jdk.net \
|
||||
jdk.rmic \
|
||||
jdk.nio.mapmode \
|
||||
jdk.scripting.nashorn \
|
||||
jdk.sctp \
|
||||
jdk.security.auth \
|
||||
|
@ -248,7 +248,7 @@ var getJibProfilesCommon = function (input, data) {
|
||||
common.main_profile_base = {
|
||||
dependencies: ["boot_jdk", "gnumake", "jtreg", "jib", "autoconf", "jmh", "jcov"],
|
||||
default_make_targets: ["product-bundles", "test-bundles", "static-libs-bundles"],
|
||||
configure_args: concat(["--enable-jtreg-failure-handler"],
|
||||
configure_args: concat("--enable-jtreg-failure-handler",
|
||||
"--with-exclude-translations=de,es,fr,it,ko,pt_BR,sv,ca,tr,cs,sk,ja_JP_A,ja_JP_HA,ja_JP_HI,ja_JP_I,zh_TW,zh_HK",
|
||||
"--disable-manpages",
|
||||
"--disable-jvm-feature-shenandoahgc",
|
||||
@ -776,6 +776,10 @@ var getJibProfilesProfiles = function (input, common, data) {
|
||||
= concat(profiles[cmpBaselineName].default_make_targets, "docs");
|
||||
}
|
||||
profiles[cmpBaselineName].make_args = [ "COMPARE_BUILD=CONF=" ];
|
||||
profiles[cmpBaselineName].configure_args = concat(
|
||||
profiles[cmpBaselineName].configure_args,
|
||||
"--with-hotspot-build-time=n/a",
|
||||
"--disable-precompiled-headers");
|
||||
// Do not inherit artifact definitions from base profile
|
||||
delete profiles[cmpBaselineName].artifacts;
|
||||
});
|
||||
@ -881,6 +885,7 @@ var getJibProfilesProfiles = function (input, common, data) {
|
||||
make_args: testOnlyMake,
|
||||
environment: {
|
||||
"BOOT_JDK": common.boot_jdk_home,
|
||||
"JT_HOME": input.get("jtreg", "home_path"),
|
||||
"JDK_IMAGE_DIR": input.get(testedProfileJdk, "home_path"),
|
||||
"TEST_IMAGE_DIR": input.get(testedProfileTest, "home_path")
|
||||
},
|
||||
@ -968,7 +973,7 @@ var getJibProfilesProfiles = function (input, common, data) {
|
||||
var getJibProfilesDependencies = function (input, common) {
|
||||
|
||||
var devkit_platform_revisions = {
|
||||
linux_x64: "gcc8.3.0-OL6.4+1.0",
|
||||
linux_x64: "gcc9.2.0-OL6.4+1.0",
|
||||
macosx_x64: "Xcode10.1-MacOSX10.14+1.0",
|
||||
solaris_x64: "SS12u4-Solaris11u1+1.0",
|
||||
solaris_sparcv9: "SS12u6-Solaris11u3+1.0",
|
||||
@ -1059,7 +1064,8 @@ var getJibProfilesDependencies = function (input, common) {
|
||||
checksum_file: "MD5_VALUES",
|
||||
file: "bundles/jtreg_bin-5.0.zip",
|
||||
environment_name: "JT_HOME",
|
||||
environment_path: input.get("jtreg", "install_path") + "/jtreg/bin"
|
||||
environment_path: input.get("jtreg", "home_path") + "/bin",
|
||||
configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"),
|
||||
},
|
||||
|
||||
jmh: {
|
||||
|
@ -1,4 +1,4 @@
|
||||
File-Date: 2020-03-16
|
||||
File-Date: 2020-04-01
|
||||
%%
|
||||
Type: language
|
||||
Subtag: aa
|
||||
@ -1530,7 +1530,7 @@ Added: 2005-10-16
|
||||
%%
|
||||
Type: language
|
||||
Subtag: adb
|
||||
Description: Adabe
|
||||
Description: Atauran
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
@ -2707,6 +2707,7 @@ Type: language
|
||||
Subtag: aoh
|
||||
Description: Arma
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: aoi
|
||||
@ -3770,6 +3771,7 @@ Type: language
|
||||
Subtag: ayy
|
||||
Description: Tayabas Ayta
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: ayz
|
||||
@ -4085,6 +4087,7 @@ Type: language
|
||||
Subtag: bbz
|
||||
Description: Babalia Creole Arabic
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
Macrolanguage: ar
|
||||
%%
|
||||
Type: language
|
||||
@ -5755,6 +5758,7 @@ Type: language
|
||||
Subtag: bpb
|
||||
Description: Barbacoas
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: bpd
|
||||
@ -6011,7 +6015,7 @@ Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: brf
|
||||
Description: Bera
|
||||
Description: Bira
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
@ -7374,6 +7378,7 @@ Type: language
|
||||
Subtag: cca
|
||||
Description: Cauca
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: ccc
|
||||
@ -7480,6 +7485,7 @@ Type: language
|
||||
Subtag: cdg
|
||||
Description: Chamari
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: cdh
|
||||
@ -7875,6 +7881,11 @@ Description: Cibak
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: ckm
|
||||
Description: Chakavian
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: ckn
|
||||
Description: Kaang Chin
|
||||
Added: 2013-09-10
|
||||
@ -8121,6 +8132,13 @@ Description: Con
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: cnp
|
||||
Description: Northern Ping Chinese
|
||||
Description: Northern Pinghua
|
||||
Added: 2020-03-28
|
||||
Macrolanguage: zh
|
||||
%%
|
||||
Type: language
|
||||
Subtag: cnr
|
||||
Description: Montenegrin
|
||||
Added: 2018-01-23
|
||||
@ -8564,6 +8582,13 @@ Description: Sochiapan Chinantec
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: csp
|
||||
Description: Southern Ping Chinese
|
||||
Description: Southern Pinghua
|
||||
Added: 2020-03-28
|
||||
Macrolanguage: zh
|
||||
%%
|
||||
Type: language
|
||||
Subtag: csq
|
||||
Description: Croatia Sign Language
|
||||
Added: 2009-07-29
|
||||
@ -9318,6 +9343,7 @@ Macrolanguage: doi
|
||||
Type: language
|
||||
Subtag: dgr
|
||||
Description: Dogrib
|
||||
Description: Tłı̨chǫ
|
||||
Added: 2005-10-16
|
||||
%%
|
||||
Type: language
|
||||
@ -9334,6 +9360,7 @@ Type: language
|
||||
Subtag: dgu
|
||||
Description: Degaru
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: dgw
|
||||
@ -9720,6 +9747,11 @@ Description: Dugwor
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: dmf
|
||||
Description: Medefaidrin
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: dmg
|
||||
Description: Upper Kinabatangan
|
||||
Added: 2009-07-29
|
||||
@ -10041,6 +10073,8 @@ Type: language
|
||||
Subtag: drr
|
||||
Description: Dororo
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
Preferred-Value: kzk
|
||||
%%
|
||||
Type: language
|
||||
Subtag: drs
|
||||
@ -10330,6 +10364,11 @@ Description: Diri
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: dwk
|
||||
Description: Dawik Kui
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: dwl
|
||||
Description: Walo Kumbe Dogon
|
||||
Added: 2009-07-29
|
||||
@ -10455,6 +10494,11 @@ Description: Karenggapa
|
||||
Added: 2013-09-10
|
||||
%%
|
||||
Type: language
|
||||
Subtag: ebc
|
||||
Description: Beginci
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: ebg
|
||||
Description: Ebughu
|
||||
Added: 2009-07-29
|
||||
@ -10576,6 +10620,7 @@ Type: language
|
||||
Subtag: ekc
|
||||
Description: Eastern Karnic
|
||||
Added: 2013-09-10
|
||||
Deprecated: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: eke
|
||||
@ -11881,6 +11926,7 @@ Added: 2009-07-29
|
||||
Type: language
|
||||
Subtag: gdh
|
||||
Description: Gadjerawang
|
||||
Description: Gajirrabeng
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
@ -11970,6 +12016,11 @@ Description: Gade
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: gef
|
||||
Description: Gerai
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: geg
|
||||
Description: Gengle
|
||||
Added: 2009-07-29
|
||||
@ -12381,6 +12432,8 @@ Type: language
|
||||
Subtag: gli
|
||||
Description: Guliguli
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
Preferred-Value: kzk
|
||||
%%
|
||||
Type: language
|
||||
Subtag: glj
|
||||
@ -12481,6 +12534,12 @@ Description: Gumalu
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: gmr
|
||||
Description: Mirning
|
||||
Description: Mirniny
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: gmv
|
||||
Description: Gamo
|
||||
Added: 2009-07-29
|
||||
@ -13155,6 +13214,7 @@ Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: gwc
|
||||
Description: Gawri
|
||||
Description: Kalami
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
@ -13859,6 +13919,11 @@ Description: Chhattisgarhi
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: hng
|
||||
Description: Hungu
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: hnh
|
||||
Description: ǁAni
|
||||
Added: 2009-07-29
|
||||
@ -14140,6 +14205,7 @@ Added: 2009-07-29
|
||||
Type: language
|
||||
Subtag: huc
|
||||
Description: ǂHua
|
||||
Description: ǂʼAmkhoe
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
@ -15910,6 +15976,7 @@ Added: 2009-07-29
|
||||
Type: language
|
||||
Subtag: kaa
|
||||
Description: Kara-Kalpak
|
||||
Description: Karakalpak
|
||||
Added: 2005-10-16
|
||||
%%
|
||||
Type: language
|
||||
@ -17067,8 +17134,9 @@ Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: kjf
|
||||
Description: Khalaj
|
||||
Description: Khalaj [Indo-Iranian]
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: kjg
|
||||
@ -17248,7 +17316,7 @@ Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: kkq
|
||||
Description: Kaiku
|
||||
Description: Kaeku
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
@ -17344,7 +17412,7 @@ Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: klj
|
||||
Description: Turkic Khalaj
|
||||
Description: Khalaj
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
@ -18497,6 +18565,7 @@ Added: 2009-07-29
|
||||
Type: language
|
||||
Subtag: kui
|
||||
Description: Kuikúro-Kalapálo
|
||||
Description: Kalapalo
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
@ -18908,6 +18977,8 @@ Type: language
|
||||
Subtag: kxl
|
||||
Description: Nepali Kurux
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
Preferred-Value: kru
|
||||
%%
|
||||
Type: language
|
||||
Subtag: kxm
|
||||
@ -18953,6 +19024,8 @@ Type: language
|
||||
Subtag: kxu
|
||||
Description: Kui (India)
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
Comments: see dwk, uki
|
||||
%%
|
||||
Type: language
|
||||
Subtag: kxv
|
||||
@ -20337,6 +20410,7 @@ Type: language
|
||||
Subtag: lmz
|
||||
Description: Lumbee
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: lna
|
||||
@ -22788,6 +22862,7 @@ Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: moe
|
||||
Description: Innu
|
||||
Description: Montagnais
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
@ -26199,6 +26274,11 @@ Description: Sangtam Naga
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: nsb
|
||||
Description: Lower Nossob
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: nsc
|
||||
Description: Nshi
|
||||
Added: 2009-07-29
|
||||
@ -26667,6 +26747,8 @@ Type: language
|
||||
Subtag: nxu
|
||||
Description: Narau
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
Preferred-Value: bpp
|
||||
%%
|
||||
Type: language
|
||||
Subtag: nxx
|
||||
@ -28166,7 +28248,7 @@ Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: pfe
|
||||
Description: Peere
|
||||
Description: Pere
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
@ -28572,6 +28654,7 @@ Type: language
|
||||
Subtag: plp
|
||||
Description: Palpa
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: plq
|
||||
@ -31132,6 +31215,8 @@ Type: language
|
||||
Subtag: sdm
|
||||
Description: Semandang
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
Comments: see ebc, gef, sdq
|
||||
%%
|
||||
Type: language
|
||||
Subtag: sdn
|
||||
@ -31150,6 +31235,11 @@ Description: Sherdukpen
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: sdq
|
||||
Description: Semandang
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: sdr
|
||||
Description: Oraon Sadri
|
||||
Added: 2009-07-29
|
||||
@ -33502,6 +33592,7 @@ Type: language
|
||||
Subtag: tbb
|
||||
Description: Tapeba
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: tbc
|
||||
@ -36240,6 +36331,11 @@ Description: Ukhwejo
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: uki
|
||||
Description: Kui (India)
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: ukk
|
||||
Description: Muak Sa-aak
|
||||
Added: 2017-02-23
|
||||
@ -36271,6 +36367,11 @@ Description: Ukue
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: ukv
|
||||
Description: Kuku
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: ukw
|
||||
Description: Ukwuani-Aboh-Ndoni
|
||||
Added: 2009-07-29
|
||||
@ -37760,6 +37861,11 @@ Description: Kunbarlang
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: wlh
|
||||
Description: Welaun
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: wli
|
||||
Description: Waioli
|
||||
Added: 2009-07-29
|
||||
@ -39232,6 +39338,11 @@ Description: Nganakarti
|
||||
Added: 2013-09-10
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xnm
|
||||
Description: Ngumbarl
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xnn
|
||||
Description: Northern Kankanay
|
||||
Added: 2009-07-29
|
||||
@ -39334,22 +39445,45 @@ Description: Pirriya
|
||||
Added: 2013-09-10
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xpb
|
||||
Description: Northeastern Tasmanian
|
||||
Description: Pyemmairrener
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xpc
|
||||
Description: Pecheneg
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xpd
|
||||
Description: Oyster Bay Tasmanian
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xpe
|
||||
Description: Liberia Kpelle
|
||||
Added: 2009-07-29
|
||||
Macrolanguage: kpe
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xpf
|
||||
Description: Southeast Tasmanian
|
||||
Description: Nuenonne
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xpg
|
||||
Description: Phrygian
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xph
|
||||
Description: North Midlands Tasmanian
|
||||
Description: Tyerrenoterpanner
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xpi
|
||||
Description: Pictish
|
||||
Added: 2009-07-29
|
||||
@ -39365,6 +39499,11 @@ Description: Kulina Pano
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xpl
|
||||
Description: Port Sorell Tasmanian
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xpm
|
||||
Description: Pumpokol
|
||||
Added: 2009-07-29
|
||||
@ -39410,11 +39549,34 @@ Description: Punic
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xpv
|
||||
Description: Northern Tasmanian
|
||||
Description: Tommeginne
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xpw
|
||||
Description: Northwestern Tasmanian
|
||||
Description: Peerapper
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xpx
|
||||
Description: Southwestern Tasmanian
|
||||
Description: Toogee
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xpy
|
||||
Description: Puyo
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xpz
|
||||
Description: Bruny Island Tasmanian
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xqa
|
||||
Description: Karakhanid
|
||||
Added: 2009-07-29
|
||||
@ -39468,6 +39630,8 @@ Type: language
|
||||
Subtag: xrq
|
||||
Description: Karranga
|
||||
Added: 2013-09-10
|
||||
Deprecated: 2020-03-28
|
||||
Preferred-Value: dmw
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xrr
|
||||
@ -39700,6 +39864,8 @@ Type: language
|
||||
Subtag: xtz
|
||||
Description: Tasmanian
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
Comments: see xpb, xpd, xpf, xph, xpl, xpv, xpw, xpx, xpz
|
||||
%%
|
||||
Type: language
|
||||
Subtag: xua
|
||||
@ -39729,6 +39895,7 @@ Added: 2009-07-29
|
||||
Type: language
|
||||
Subtag: xul
|
||||
Description: Ngunawal
|
||||
Description: Nunukul
|
||||
Added: 2013-09-10
|
||||
%%
|
||||
Type: language
|
||||
@ -41321,6 +41488,11 @@ Description: Zari
|
||||
Added: 2009-07-29
|
||||
%%
|
||||
Type: language
|
||||
Subtag: zba
|
||||
Description: Balaibalan
|
||||
Added: 2020-03-28
|
||||
%%
|
||||
Type: language
|
||||
Subtag: zbc
|
||||
Description: Central Berawan
|
||||
Added: 2009-07-29
|
||||
@ -41486,6 +41658,8 @@ Type: language
|
||||
Subtag: zir
|
||||
Description: Ziriya
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
Preferred-Value: scv
|
||||
%%
|
||||
Type: language
|
||||
Subtag: ziw
|
||||
@ -42463,6 +42637,7 @@ Type: extlang
|
||||
Subtag: bbz
|
||||
Description: Babalia Creole Arabic
|
||||
Added: 2009-07-29
|
||||
Deprecated: 2020-03-28
|
||||
Preferred-Value: bbz
|
||||
Prefix: ar
|
||||
Macrolanguage: ar
|
||||
@ -42580,6 +42755,15 @@ Prefix: zh
|
||||
Macrolanguage: zh
|
||||
%%
|
||||
Type: extlang
|
||||
Subtag: cnp
|
||||
Description: Northern Ping Chinese
|
||||
Description: Northern Pinghua
|
||||
Added: 2020-03-28
|
||||
Preferred-Value: cnp
|
||||
Prefix: zh
|
||||
Macrolanguage: zh
|
||||
%%
|
||||
Type: extlang
|
||||
Subtag: coa
|
||||
Description: Cocos Islands Malay
|
||||
Added: 2009-07-29
|
||||
@ -42647,6 +42831,15 @@ Preferred-Value: csn
|
||||
Prefix: sgn
|
||||
%%
|
||||
Type: extlang
|
||||
Subtag: csp
|
||||
Description: Southern Ping Chinese
|
||||
Description: Southern Pinghua
|
||||
Added: 2020-03-28
|
||||
Preferred-Value: csp
|
||||
Prefix: zh
|
||||
Macrolanguage: zh
|
||||
%%
|
||||
Type: extlang
|
||||
Subtag: csq
|
||||
Description: Croatia Sign Language
|
||||
Added: 2009-07-29
|
||||
@ -46630,6 +46823,12 @@ Comments: Denotes conventions established by the Academia Brasileira de
|
||||
Letras in 1943 and generally used in Brazil until 2009
|
||||
%%
|
||||
Type: variant
|
||||
Subtag: akuapem
|
||||
Description: Akuapem Twi
|
||||
Added: 2017-06-05
|
||||
Prefix: tw
|
||||
%%
|
||||
Type: variant
|
||||
Subtag: alalc97
|
||||
Description: ALA-LC Romanization, 1997 edition
|
||||
Added: 2009-12-09
|
||||
@ -46648,12 +46847,6 @@ Comments: Aluku dialect of the "Busi Nenge Tongo" English-based Creole
|
||||
continuum in Eastern Suriname and Western French Guiana
|
||||
%%
|
||||
Type: variant
|
||||
Subtag: akuapem
|
||||
Description: Akuapem Twi
|
||||
Added: 2017-06-05
|
||||
Prefix: tw
|
||||
%%
|
||||
Type: variant
|
||||
Subtag: ao1990
|
||||
Description: Portuguese Language Orthographic Agreement of 1990 (Acordo
|
||||
Ortográfico da Língua Portuguesa de 1990)
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -87,8 +87,16 @@ endif
|
||||
# Define external dependencies
|
||||
|
||||
# Latest that could be made to work.
|
||||
GCC_VER := 8.3.0
|
||||
ifeq ($(GCC_VER), 8.3.0)
|
||||
GCC_VER := 9.2.0
|
||||
ifeq ($(GCC_VER), 9.2.0)
|
||||
gcc_ver := gcc-9.2.0
|
||||
binutils_ver := binutils-2.34
|
||||
ccache_ver := 3.7.3
|
||||
mpfr_ver := mpfr-3.1.5
|
||||
gmp_ver := gmp-6.1.2
|
||||
mpc_ver := mpc-1.0.3
|
||||
gdb_ver := gdb-8.3
|
||||
else ifeq ($(GCC_VER), 8.3.0)
|
||||
gcc_ver := gcc-8.3.0
|
||||
binutils_ver := binutils-2.32
|
||||
ccache_ver := 3.7.3
|
||||
|
@ -40,10 +40,10 @@ mkdir -p $BUILD_DIR $JAR_DIR
|
||||
cd $JAR_DIR
|
||||
rm -f *
|
||||
|
||||
wget http://central.maven.org/maven2/org/apache/commons/commons-math3/$COMMONS_MATH3_VERSION/commons-math3-$COMMONS_MATH3_VERSION.jar
|
||||
wget http://central.maven.org/maven2/net/sf/jopt-simple/jopt-simple/$JOPT_SIMPLE_VERSION/jopt-simple-$JOPT_SIMPLE_VERSION.jar
|
||||
wget http://central.maven.org/maven2/org/openjdk/jmh/jmh-core/$JMH_VERSION/jmh-core-$JMH_VERSION.jar
|
||||
wget http://central.maven.org/maven2/org/openjdk/jmh/jmh-generator-annprocess/$JMH_VERSION/jmh-generator-annprocess-$JMH_VERSION.jar
|
||||
wget https://repo.maven.apache.org/maven2/org/apache/commons/commons-math3/$COMMONS_MATH3_VERSION/commons-math3-$COMMONS_MATH3_VERSION.jar
|
||||
wget https://repo.maven.apache.org/maven2/net/sf/jopt-simple/jopt-simple/$JOPT_SIMPLE_VERSION/jopt-simple-$JOPT_SIMPLE_VERSION.jar
|
||||
wget https://repo.maven.apache.org/maven2/org/openjdk/jmh/jmh-core/$JMH_VERSION/jmh-core-$JMH_VERSION.jar
|
||||
wget https://repo.maven.apache.org/maven2/org/openjdk/jmh/jmh-generator-annprocess/$JMH_VERSION/jmh-generator-annprocess-$JMH_VERSION.jar
|
||||
|
||||
tar -cvzf ../$BUNDLE_NAME *
|
||||
|
||||
|
@ -75,6 +75,10 @@ CFLAGS_VM_VERSION := \
|
||||
-DCPU='"$(OPENJDK_TARGET_CPU_VM_VERSION)"' \
|
||||
#
|
||||
|
||||
ifneq ($(HOTSPOT_BUILD_TIME), )
|
||||
CFLAGS_VM_VERSION += -DHOTSPOT_BUILD_TIME='"$(HOTSPOT_BUILD_TIME)"'
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
# Disabled warnings
|
||||
|
||||
|
@ -173,6 +173,7 @@ endif
|
||||
ifneq ($(call check-jvm-feature, jfr), true)
|
||||
JVM_CFLAGS_FEATURES += -DINCLUDE_JFR=0
|
||||
JVM_EXCLUDE_PATTERNS += jfr
|
||||
JVM_EXCLUDE_FILES += compilerEvent.cpp
|
||||
endif
|
||||
|
||||
################################################################################
|
||||
|
@ -191,6 +191,7 @@ class Bundle {
|
||||
String[] cldrBundles = getCLDRPath().split(",");
|
||||
|
||||
// myMap contains resources for id.
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> myMap = new HashMap<>();
|
||||
int index;
|
||||
for (index = 0; index < cldrBundles.length; index++) {
|
||||
@ -230,10 +231,12 @@ class Bundle {
|
||||
}
|
||||
|
||||
for (String k : COMPACT_NUMBER_PATTERN_KEYS) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> patterns = (List<String>) myMap.remove(k);
|
||||
if (patterns != null) {
|
||||
// Convert the map value from List<String> to String[], replacing any missing
|
||||
// entry from the parents map, if any.
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<String> pList = (List<String>)parentsMap.get(k);
|
||||
int size = patterns.size();
|
||||
int psize = pList != null ? pList.size() : 0;
|
||||
|
@ -434,7 +434,7 @@ public class CLDRConverter {
|
||||
parentData.keySet().stream()
|
||||
.filter(key -> key.startsWith(PARENT_LOCALE_PREFIX))
|
||||
.forEach(key -> {
|
||||
parentLocalesMap.put(key, new TreeSet(
|
||||
parentLocalesMap.put(key, new TreeSet<String>(
|
||||
Arrays.asList(((String)parentData.get(key)).split(" "))));
|
||||
});
|
||||
|
||||
@ -481,7 +481,7 @@ public class CLDRConverter {
|
||||
});
|
||||
}
|
||||
|
||||
private static void parseLDMLFile(File srcfile, AbstractLDMLHandler handler) throws Exception {
|
||||
private static void parseLDMLFile(File srcfile, AbstractLDMLHandler<?> handler) throws Exception {
|
||||
info("..... Parsing " + srcfile.getName() + " .....");
|
||||
SAXParserFactory pf = SAXParserFactory.newInstance();
|
||||
pf.setValidating(true);
|
||||
@ -574,7 +574,7 @@ public class CLDRConverter {
|
||||
* Translate the aliases into the real entries in the bundle map.
|
||||
*/
|
||||
static void handleAliases(Map<String, Object> bundleMap) {
|
||||
Set bundleKeys = bundleMap.keySet();
|
||||
Set<String> bundleKeys = bundleMap.keySet();
|
||||
try {
|
||||
for (String key : aliases.keySet()) {
|
||||
String targetKey = aliases.get(key);
|
||||
@ -1158,10 +1158,10 @@ public class CLDRConverter {
|
||||
|
||||
private static Stream<String> pluralRulesStream() {
|
||||
return handlerPlurals.getData().entrySet().stream()
|
||||
.filter(e -> !((Map<String, String>)e.getValue()).isEmpty())
|
||||
.filter(e -> !(e.getValue()).isEmpty())
|
||||
.map(e -> {
|
||||
String loc = e.getKey();
|
||||
Map<String, String> rules = (Map<String, String>)e.getValue();
|
||||
Map<String, String> rules = e.getValue();
|
||||
return " {\"" + loc + "\", \"" +
|
||||
rules.entrySet().stream()
|
||||
.map(rule -> rule.getKey() + ":" + rule.getValue().replaceFirst("@.*", ""))
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -40,7 +40,7 @@ import org.xml.sax.SAXException;
|
||||
* plurals.xml
|
||||
*/
|
||||
|
||||
class PluralsParseHandler extends AbstractLDMLHandler<Object> {
|
||||
class PluralsParseHandler extends AbstractLDMLHandler<Map<String, String>> {
|
||||
@Override
|
||||
public InputSource resolveEntity(String publicID, String systemID) throws IOException, SAXException {
|
||||
// avoid HTTP traffic to unicode.org
|
||||
@ -82,13 +82,13 @@ class PluralsParseHandler extends AbstractLDMLHandler<Object> {
|
||||
switch (qName) {
|
||||
case "pluralRule":
|
||||
assert !(currentContainer instanceof Entry);
|
||||
Entry entry = (Entry)currentContainer;
|
||||
Entry<?> entry = (Entry<?>)currentContainer;
|
||||
final String count = entry.getKey();
|
||||
final String rule = (String)entry.getValue();
|
||||
String locales = ((KeyContainer)(currentContainer.getParent())).getKey();
|
||||
Arrays.stream(locales.split("\\s"))
|
||||
.forEach(loc -> {
|
||||
Map<String, String> rules = (Map<String, String>)get(loc);
|
||||
Map<String, String> rules = get(loc);
|
||||
if (rules == null) {
|
||||
rules = new HashMap<>();
|
||||
put(loc, rules);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -139,7 +139,7 @@ class DTDBuilder extends DTD {
|
||||
}
|
||||
int i = namesVector.size();
|
||||
namesVector.addElement(name);
|
||||
namesHash.put(name, new Integer(i));
|
||||
namesHash.put(name, i);
|
||||
return (short) i;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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,8 +92,8 @@ class DTDInputStream extends FilterReader implements DTDConstants {
|
||||
* Push an entire input stream
|
||||
*/
|
||||
void push(Reader in) throws IOException {
|
||||
stack.push(new Integer(ln));
|
||||
stack.push(new Integer(ch));
|
||||
stack.push(Integer.valueOf(ln));
|
||||
stack.push(Integer.valueOf(ch));
|
||||
stack.push(this.in);
|
||||
this.in = in;
|
||||
ch = in.read();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -87,12 +87,12 @@ public class GenerateBreakIteratorData {
|
||||
ResourceBundle rules, info;
|
||||
|
||||
info = (ResourceBundle) Class.forName(
|
||||
localizedBundleName("sun.text.resources", "BreakIteratorInfo")).newInstance();
|
||||
localizedBundleName("sun.text.resources", "BreakIteratorInfo")).getDeclaredConstructor().newInstance();
|
||||
|
||||
classNames = info.getStringArray("BreakIteratorClasses");
|
||||
|
||||
rules = (ResourceBundle) Class.forName(
|
||||
localizedBundleName("sun.text.resources", "BreakIteratorRules")).newInstance();
|
||||
localizedBundleName("sun.text.resources", "BreakIteratorRules")).getDeclaredConstructor().newInstance();
|
||||
|
||||
if (info.containsKey("CharacterData")) {
|
||||
generateDataFile(info.getString("CharacterData"),
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -290,7 +290,7 @@ class RuleBasedBreakIteratorBuilder {
|
||||
}
|
||||
|
||||
lastOpen = c;
|
||||
parenStack.push(new Character((char)c));
|
||||
parenStack.push(Character.valueOf((char)c));
|
||||
if (c == '<') {
|
||||
sawVarName = true;
|
||||
}
|
||||
@ -902,11 +902,11 @@ class RuleBasedBreakIteratorBuilder {
|
||||
// if we're adding rules to the backward state table, mark the initial state
|
||||
// as a looping state
|
||||
if (!forward) {
|
||||
loopingStates.addElement(new Integer(1));
|
||||
loopingStates.addElement(Integer.valueOf(1));
|
||||
}
|
||||
|
||||
// put the current state on the decision point list before we start
|
||||
decisionPointList.addElement(new Integer(currentState)); // we want currentState to
|
||||
decisionPointList.addElement(Integer.valueOf(currentState)); // we want currentState to
|
||||
// be 1 here...
|
||||
currentState = tempStateTable.size() - 1; // but after that, we want it to be
|
||||
// 1 less than the state number of the next state
|
||||
@ -978,7 +978,7 @@ class RuleBasedBreakIteratorBuilder {
|
||||
// if the period is followed by an asterisk, then just set the current
|
||||
// state to loop back on itself
|
||||
if (p + 1 < rule.length() && rule.charAt(p + 1) == '*' && state[0] != 0) {
|
||||
decisionPointList.addElement(new Integer(state[0]));
|
||||
decisionPointList.addElement(Integer.valueOf(state[0]));
|
||||
pendingChars = "";
|
||||
++p;
|
||||
}
|
||||
@ -1012,7 +1012,7 @@ class RuleBasedBreakIteratorBuilder {
|
||||
// it to the end of the state table
|
||||
int newState = tempStateTable.size();
|
||||
if (loopingStates.size() != 0) {
|
||||
statesToBackfill.addElement(new Integer(newState));
|
||||
statesToBackfill.addElement(Integer.valueOf(newState));
|
||||
}
|
||||
state = new short[numCategories + 1];
|
||||
if (sawEarlyBreak) {
|
||||
@ -1032,7 +1032,7 @@ class RuleBasedBreakIteratorBuilder {
|
||||
lastState = currentState;
|
||||
do {
|
||||
++currentState;
|
||||
decisionPointList.addElement(new Integer(currentState));
|
||||
decisionPointList.addElement(Integer.valueOf(currentState));
|
||||
} while (currentState + 1 < tempStateTable.size());
|
||||
}
|
||||
}
|
||||
@ -1058,7 +1058,7 @@ class RuleBasedBreakIteratorBuilder {
|
||||
if (c == '*') {
|
||||
for (int i = lastState + 1; i < tempStateTable.size(); i++) {
|
||||
Vector<Integer> temp = new Vector<>();
|
||||
temp.addElement(new Integer(i));
|
||||
temp.addElement(Integer.valueOf(i));
|
||||
updateStateTable(temp, pendingChars, (short)(lastState + 1));
|
||||
}
|
||||
}
|
||||
@ -1121,7 +1121,7 @@ class RuleBasedBreakIteratorBuilder {
|
||||
|
||||
// add the current state to the decision point list (add it at the
|
||||
// BEGINNING so we can find it later)
|
||||
decisionPointList.insertElementAt(new Integer(currentState), 0);
|
||||
decisionPointList.insertElementAt(Integer.valueOf(currentState), 0);
|
||||
|
||||
// finally, push a copy of the current decision point list onto the
|
||||
// stack (this keeps track of the active decision point list before
|
||||
@ -1208,7 +1208,7 @@ class RuleBasedBreakIteratorBuilder {
|
||||
for (int i = 0; i < tempState.length; i++) {
|
||||
if (tempState[i] > tempStateNum) {
|
||||
updateStateTable(exitPoints,
|
||||
new Character((char)(i + 0x100)).toString(),
|
||||
Character.valueOf((char)(i + 0x100)).toString(),
|
||||
tempState[i]);
|
||||
}
|
||||
}
|
||||
@ -1330,7 +1330,7 @@ class RuleBasedBreakIteratorBuilder {
|
||||
short[] newValues,
|
||||
Vector<Integer> rowsBeingUpdated) {
|
||||
short[] oldValues = tempStateTable.elementAt(rowNum);
|
||||
boolean isLoopingState = loopingStates.contains(new Integer(rowNum));
|
||||
boolean isLoopingState = loopingStates.contains(Integer.valueOf(rowNum));
|
||||
|
||||
// for each of the cells in the rows we're reconciling, do...
|
||||
for (int i = 0; i < oldValues.length; i++) {
|
||||
@ -1343,7 +1343,7 @@ class RuleBasedBreakIteratorBuilder {
|
||||
// if oldValues is a looping state and the state the current cell points to
|
||||
// is too, then we can just stomp over the current value of that cell (and
|
||||
// set the clear-looping-states flag if necessary)
|
||||
else if (isLoopingState && loopingStates.contains(new Integer(oldValues[i]))) {
|
||||
else if (isLoopingState && loopingStates.contains(Integer.valueOf(oldValues[i]))) {
|
||||
if (newValues[i] != 0) {
|
||||
if (oldValues[i] == 0) {
|
||||
clearLoopingStates = true;
|
||||
@ -1401,29 +1401,29 @@ class RuleBasedBreakIteratorBuilder {
|
||||
|
||||
// if the decision point list contains either of the parent rows,
|
||||
// update it to include the new row as well
|
||||
if ((decisionPointList.contains(new Integer(oldRowNum))
|
||||
|| decisionPointList.contains(new Integer(newRowNum)))
|
||||
&& !decisionPointList.contains(new Integer(combinedRowNum))
|
||||
if ((decisionPointList.contains(Integer.valueOf(oldRowNum))
|
||||
|| decisionPointList.contains(Integer.valueOf(newRowNum)))
|
||||
&& !decisionPointList.contains(Integer.valueOf(combinedRowNum))
|
||||
) {
|
||||
decisionPointList.addElement(new Integer(combinedRowNum));
|
||||
decisionPointList.addElement(Integer.valueOf(combinedRowNum));
|
||||
}
|
||||
|
||||
// do the same thing with the list of rows being updated
|
||||
if ((rowsBeingUpdated.contains(new Integer(oldRowNum))
|
||||
|| rowsBeingUpdated.contains(new Integer(newRowNum)))
|
||||
&& !rowsBeingUpdated.contains(new Integer(combinedRowNum))
|
||||
if ((rowsBeingUpdated.contains(Integer.valueOf(oldRowNum))
|
||||
|| rowsBeingUpdated.contains(Integer.valueOf(newRowNum)))
|
||||
&& !rowsBeingUpdated.contains(Integer.valueOf(combinedRowNum))
|
||||
) {
|
||||
decisionPointList.addElement(new Integer(combinedRowNum));
|
||||
decisionPointList.addElement(Integer.valueOf(combinedRowNum));
|
||||
}
|
||||
// now (groan) do the same thing for all the entries on the
|
||||
// decision point stack
|
||||
for (int k = 0; k < decisionPointStack.size(); k++) {
|
||||
Vector<Integer> dpl = decisionPointStack.elementAt(k);
|
||||
if ((dpl.contains(new Integer(oldRowNum))
|
||||
|| dpl.contains(new Integer(newRowNum)))
|
||||
&& !dpl.contains(new Integer(combinedRowNum))
|
||||
if ((dpl.contains(Integer.valueOf(oldRowNum))
|
||||
|| dpl.contains(Integer.valueOf(newRowNum)))
|
||||
&& !dpl.contains(Integer.valueOf(combinedRowNum))
|
||||
) {
|
||||
dpl.addElement(new Integer(combinedRowNum));
|
||||
dpl.addElement(Integer.valueOf(combinedRowNum));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1536,10 +1536,10 @@ class RuleBasedBreakIteratorBuilder {
|
||||
private void eliminateBackfillStates(int baseState) {
|
||||
|
||||
// don't do anything unless this state is actually in the backfill list...
|
||||
if (statesToBackfill.contains(new Integer(baseState))) {
|
||||
if (statesToBackfill.contains(Integer.valueOf(baseState))) {
|
||||
|
||||
// if it is, take it out
|
||||
statesToBackfill.removeElement(new Integer(baseState));
|
||||
statesToBackfill.removeElement(Integer.valueOf(baseState));
|
||||
|
||||
// then go through and recursively call this function for every
|
||||
// state that the base state points to
|
||||
@ -1608,7 +1608,7 @@ class RuleBasedBreakIteratorBuilder {
|
||||
|
||||
int[] rowNumMap = new int[tempStateTable.size()];
|
||||
Stack<Integer> rowsToFollow = new Stack<>();
|
||||
rowsToFollow.push(new Integer(1));
|
||||
rowsToFollow.push(Integer.valueOf(1));
|
||||
rowNumMap[1] = 1;
|
||||
|
||||
// determine which states are no longer reachable from the start state
|
||||
@ -1622,7 +1622,7 @@ class RuleBasedBreakIteratorBuilder {
|
||||
if (row[i] != 0) {
|
||||
if (rowNumMap[row[i]] == 0) {
|
||||
rowNumMap[row[i]] = row[i];
|
||||
rowsToFollow.push(new Integer(row[i]));
|
||||
rowsToFollow.push(Integer.valueOf(row[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package build.tools.generatecharacter;
|
||||
|
||||
import java.io.*;
|
||||
|
@ -1,3 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package build.tools.generatecharacter;
|
||||
|
||||
import java.util.regex.*;
|
||||
@ -118,7 +143,7 @@ public class CharacterScript {
|
||||
// Character.getType() != Character.UNASSIGNED
|
||||
// first (return UNKNOWN for unassigned)
|
||||
|
||||
ArrayList<int[]> list = new ArrayList();
|
||||
ArrayList<int[]> list = new ArrayList<>();
|
||||
list.add(scripts[0]);
|
||||
|
||||
int[] last = scripts[0];
|
||||
@ -156,7 +181,7 @@ public class CharacterScript {
|
||||
}
|
||||
|
||||
for (i = 0; i < list.size(); i++) {
|
||||
int[] a = (int[])list.get(i);
|
||||
int[] a = list.get(i);
|
||||
String name = "UNKNOWN";
|
||||
if (a[2] != -1)
|
||||
name = names[a[2]].toUpperCase(Locale.US);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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,16 +45,16 @@ public class PrintCharacterRanges {
|
||||
int end() { return end; }
|
||||
}
|
||||
|
||||
private static List/*<BooleanRange>*/ recoverBooleanRanges(String methodName) throws Exception {
|
||||
List result = new ArrayList();
|
||||
private static List<BooleanRange> recoverBooleanRanges(String methodName) throws Exception {
|
||||
List<BooleanRange> result = new ArrayList<>();
|
||||
int currentRangeStart = -1;
|
||||
Method method = Character.class.getDeclaredMethod(methodName, new Class[] { Character.TYPE });
|
||||
Method method = Character.class.getDeclaredMethod(methodName, new Class<?>[] { Character.TYPE });
|
||||
if (method == null) {
|
||||
throw new RuntimeException("No method \"" + methodName + "\"(C) found");
|
||||
}
|
||||
|
||||
for (int i = 0; i <= 255; i++) {
|
||||
boolean methodRes = ((Boolean) method.invoke(null, new Object[] { new Character((char) i) })).booleanValue();
|
||||
boolean methodRes = ((Boolean) method.invoke(null, new Object[] { Character.valueOf((char) i) })).booleanValue();
|
||||
if (methodRes) {
|
||||
if (currentRangeStart < 0) {
|
||||
currentRangeStart = i;
|
||||
@ -91,17 +91,17 @@ public class PrintCharacterRanges {
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
private static void printBooleanRanges(List/*<BooleanRange>*/ ranges, String methodName) {
|
||||
private static void printBooleanRanges(List<BooleanRange> ranges, String methodName) {
|
||||
System.out.print(methodName + ":");
|
||||
for (Iterator iter = ranges.iterator(); iter.hasNext();) {
|
||||
BooleanRange range = (BooleanRange) iter.next();
|
||||
for (Iterator<BooleanRange> iter = ranges.iterator(); iter.hasNext();) {
|
||||
BooleanRange range = iter.next();
|
||||
System.out.print(" [ " + describe(range.begin()) + ", " + describe(range.end()) + " ]");
|
||||
}
|
||||
System.out.println("");
|
||||
}
|
||||
|
||||
private static void recoverAndPrintBooleanRanges(String methodName) throws Exception {
|
||||
List ranges = recoverBooleanRanges(methodName);
|
||||
List<BooleanRange> ranges = recoverBooleanRanges(methodName);
|
||||
printBooleanRanges(ranges, methodName);
|
||||
}
|
||||
|
||||
@ -121,17 +121,17 @@ public class PrintCharacterRanges {
|
||||
int offset() { return offset; }
|
||||
}
|
||||
|
||||
private static List/*<ShiftRange>*/ recoverShiftRanges(String methodName) throws Exception {
|
||||
List result = new ArrayList();
|
||||
private static List<ShiftRange> recoverShiftRanges(String methodName) throws Exception {
|
||||
List<ShiftRange> result = new ArrayList<>();
|
||||
int currentRangeStart = -1;
|
||||
int currentRangeOffset = -1;
|
||||
Method method = Character.class.getDeclaredMethod(methodName, new Class[] { Character.TYPE });
|
||||
Method method = Character.class.getDeclaredMethod(methodName, new Class<?>[] { Character.TYPE });
|
||||
if (method == null) {
|
||||
throw new RuntimeException("No method \"" + methodName + "\"(C) found");
|
||||
}
|
||||
|
||||
for (int i = 0; i <= 255; i++) {
|
||||
char methodRes = ((Character) method.invoke(null, new Object[] { new Character((char) i) })).charValue();
|
||||
char methodRes = ((Character) method.invoke(null, new Object[] { Character.valueOf((char) i) })).charValue();
|
||||
if (methodRes != i) {
|
||||
int offset = methodRes - i;
|
||||
if (currentRangeStart < 0) {
|
||||
@ -155,11 +155,11 @@ public class PrintCharacterRanges {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void printShiftRanges(List/*<ShiftRange>*/ ranges, String methodName) {
|
||||
private static void printShiftRanges(List<ShiftRange> ranges, String methodName) {
|
||||
System.out.print(methodName + ":");
|
||||
boolean isFirst = true;
|
||||
for (Iterator iter = ranges.iterator(); iter.hasNext();) {
|
||||
ShiftRange range = (ShiftRange) iter.next();
|
||||
for (Iterator<ShiftRange> iter = ranges.iterator(); iter.hasNext();) {
|
||||
ShiftRange range = iter.next();
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
} else {
|
||||
@ -173,7 +173,7 @@ public class PrintCharacterRanges {
|
||||
}
|
||||
|
||||
private static void recoverAndPrintShiftRanges(String methodName) throws Exception {
|
||||
List ranges = recoverShiftRanges(methodName);
|
||||
List<ShiftRange> ranges = recoverShiftRanges(methodName);
|
||||
printShiftRanges(ranges, methodName);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -322,7 +322,7 @@ public class GenerateCurrencyData {
|
||||
specialCaseNewCurrenciesDefaultFractionDigits[specialCaseCount] = getDefaultFractionDigits(newCurrency);
|
||||
specialCaseNewCurrenciesNumericCode[specialCaseCount] = getNumericCode(newCurrency);
|
||||
}
|
||||
specialCaseMap.put(currencyInfo, new Integer(specialCaseCount));
|
||||
specialCaseMap.put(currencyInfo, Integer.valueOf(specialCaseCount));
|
||||
return specialCaseCount++;
|
||||
}
|
||||
|
||||
|
@ -33,10 +33,12 @@ import java.nio.file.Paths;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* This tool reads the IANA Language Subtag Registry data file downloaded from
|
||||
@ -75,32 +77,49 @@ public class EquivMapsGenerator {
|
||||
String type = null;
|
||||
String tag = null;
|
||||
String preferred = null;
|
||||
String prefix = null;
|
||||
|
||||
for (String line : Files.readAllLines(Paths.get(filename),
|
||||
Charset.forName("UTF-8"))) {
|
||||
line = line.toLowerCase(Locale.ROOT);
|
||||
int index = line.indexOf(' ')+1;
|
||||
int index = line.indexOf(' ') + 1;
|
||||
if (line.startsWith("file-date:")) {
|
||||
LSRrevisionDate = line.substring(index);
|
||||
} else if (line.startsWith("type:")) {
|
||||
type = line.substring(index);
|
||||
} else if (line.startsWith("tag:") || line.startsWith("subtag:")) {
|
||||
tag = line.substring(index);
|
||||
} else if (line.startsWith("preferred-value:")
|
||||
&& !type.equals("extlang")) {
|
||||
} else if (line.startsWith("preferred-value:")) {
|
||||
preferred = line.substring(index);
|
||||
processDeprecatedData(type, tag, preferred);
|
||||
} else if (line.startsWith("prefix:")) {
|
||||
prefix = line.substring(index);
|
||||
} else if (line.equals("%%")) {
|
||||
processDeprecatedData(type, tag, preferred, prefix);
|
||||
type = null;
|
||||
tag = null;
|
||||
preferred = null;
|
||||
prefix = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Last entry
|
||||
processDeprecatedData(type, tag, preferred, prefix);
|
||||
}
|
||||
|
||||
private static void processDeprecatedData(String type,
|
||||
String tag,
|
||||
String preferred) {
|
||||
String preferred,
|
||||
String prefix) {
|
||||
StringBuilder sb;
|
||||
|
||||
if (type == null || tag == null || preferred == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type.equals("extlang") && prefix != null) {
|
||||
tag = prefix + "-" + tag;
|
||||
}
|
||||
|
||||
if (type.equals("region") || type.equals("variant")) {
|
||||
if (!initialRegionVariantMap.containsKey(preferred)) {
|
||||
sb = new StringBuilder("-");
|
||||
@ -113,7 +132,7 @@ public class EquivMapsGenerator {
|
||||
+ " A region/variant subtag \"" + preferred
|
||||
+ "\" is registered for more than one subtags.");
|
||||
}
|
||||
} else { // language, grandfahered, and redundant
|
||||
} else { // language, extlang, grandfathered, and redundant
|
||||
if (!initialLanguageMap.containsKey(preferred)) {
|
||||
sb = new StringBuilder(preferred);
|
||||
sb.append(',');
|
||||
@ -131,7 +150,12 @@ public class EquivMapsGenerator {
|
||||
private static void generateEquivalentMap() {
|
||||
String[] subtags;
|
||||
for (String preferred : initialLanguageMap.keySet()) {
|
||||
subtags = initialLanguageMap.get(preferred).toString().split(",");
|
||||
// There are cases where the same tag may appear in two entries, e.g.,
|
||||
// "yue" is defined both as extlang and redundant. Remove the dup.
|
||||
subtags = Arrays.stream(initialLanguageMap.get(preferred).toString().split(","))
|
||||
.distinct()
|
||||
.collect(Collectors.toList())
|
||||
.toArray(new String[0]);
|
||||
|
||||
if (subtags.length == 2) {
|
||||
sortedLanguageMap1.put(subtags[0], subtags[1]);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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 build.tools.jdwpgen;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
class Parse {
|
||||
|
||||
@ -144,12 +145,18 @@ class Parse {
|
||||
return null;
|
||||
} else {
|
||||
try {
|
||||
Node node = (Node)proto.getClass().newInstance();
|
||||
Node node = (Node)proto.getClass().getDeclaredConstructor().newInstance();
|
||||
node.set(kind, list, izer.lineno());
|
||||
return node;
|
||||
} catch (InstantiationException exc) {
|
||||
error(exc.toString());
|
||||
return null;
|
||||
} catch (NoSuchMethodException exc) {
|
||||
error(exc.toString());
|
||||
return null;
|
||||
} catch (InvocationTargetException exc) {
|
||||
error(exc.toString());
|
||||
return null;
|
||||
} catch (IllegalAccessException exc) {
|
||||
error(exc.toString());
|
||||
return null;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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,7 +67,7 @@ class TzdbZoneRulesProvider {
|
||||
}
|
||||
|
||||
public Set<String> getZoneIds() {
|
||||
return new TreeSet(regionIds);
|
||||
return new TreeSet<String>(regionIds);
|
||||
}
|
||||
|
||||
public Map<String, String> getAliasMap() {
|
||||
@ -100,6 +100,7 @@ class TzdbZoneRulesProvider {
|
||||
return (ZoneRules)obj;
|
||||
}
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
ZoneRules zrules = buildRules(zoneId, (List<ZoneLine>)obj);
|
||||
zones.put(zoneId, zrules);
|
||||
return zrules;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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,11 +47,11 @@ public class WrapperGenerator {
|
||||
String defaultBaseClass = "XWrapperBase";
|
||||
|
||||
String compile_options = "-lX11";
|
||||
static Hashtable symbolTable = new Hashtable();
|
||||
static Hashtable sizeTable32bit = new Hashtable();
|
||||
static Hashtable sizeTable64bit = new Hashtable();
|
||||
static Hashtable knownSizes32 = new Hashtable();
|
||||
static Hashtable knownSizes64 = new Hashtable();
|
||||
static Hashtable<String, BaseType> symbolTable = new Hashtable<>();
|
||||
static Hashtable<String, String> sizeTable32bit = new Hashtable<>();
|
||||
static Hashtable<String, String> sizeTable64bit = new Hashtable<>();
|
||||
static Hashtable<String, Integer> knownSizes32 = new Hashtable<>();
|
||||
static Hashtable<String, Integer> knownSizes64 = new Hashtable<>();
|
||||
static {
|
||||
/*
|
||||
knownSizes64.put("", Integer.valueOf());
|
||||
@ -391,7 +391,7 @@ public class WrapperGenerator {
|
||||
alias = true;
|
||||
aliasName = attributes[4];
|
||||
} else if (type == TYPE_ARRAY || type == TYPE_PTR || type == TYPE_STRUCT) {
|
||||
referencedType = (BaseType)symbolTable.get(mod);
|
||||
referencedType = symbolTable.get(mod);
|
||||
if (referencedType == null) {
|
||||
log.warning("Can't find type for name " + mod);
|
||||
}
|
||||
@ -457,7 +457,7 @@ public class WrapperGenerator {
|
||||
|
||||
private static class StructType extends BaseType {
|
||||
|
||||
Vector members;
|
||||
Vector<BaseType> members;
|
||||
String description;
|
||||
boolean packed;
|
||||
int size;
|
||||
@ -472,7 +472,7 @@ public class WrapperGenerator {
|
||||
*/
|
||||
public StructType(String _desc)
|
||||
{
|
||||
members = new Vector();
|
||||
members = new Vector<>();
|
||||
parseDescription(_desc);
|
||||
}
|
||||
public int getNumFields()
|
||||
@ -495,7 +495,7 @@ public class WrapperGenerator {
|
||||
return description;
|
||||
}
|
||||
|
||||
public Enumeration getMembers()
|
||||
public Enumeration<BaseType> getMembers()
|
||||
{
|
||||
return members.elements();
|
||||
}
|
||||
@ -545,8 +545,8 @@ public class WrapperGenerator {
|
||||
* Returns String containing Java code calculating size of the structure depending on the data model
|
||||
*/
|
||||
public String getSize() {
|
||||
String s32 = (String) WrapperGenerator.sizeTable32bit.get(getName());
|
||||
String s64 = (String) WrapperGenerator.sizeTable64bit.get(getName());
|
||||
String s32 = WrapperGenerator.sizeTable32bit.get(getName());
|
||||
String s64 = WrapperGenerator.sizeTable64bit.get(getName());
|
||||
if (s32 == null || s64 == null) {
|
||||
return (s32 == null)?(s64):(s32);
|
||||
}
|
||||
@ -558,8 +558,8 @@ public class WrapperGenerator {
|
||||
}
|
||||
public String getOffset(AtomicType atp) {
|
||||
String key = getName()+"."+(atp.isAlias() ? atp.getAliasName() : atp.getName());
|
||||
String s64 = (String) WrapperGenerator.sizeTable64bit.get(key);
|
||||
String s32 = (String) WrapperGenerator.sizeTable32bit.get(key);
|
||||
String s64 = WrapperGenerator.sizeTable64bit.get(key);
|
||||
String s32 = WrapperGenerator.sizeTable32bit.get(key);
|
||||
if (s32 == null || s64 == null) {
|
||||
return (s32 == null)?(s64):(s32);
|
||||
}
|
||||
@ -573,7 +573,7 @@ public class WrapperGenerator {
|
||||
|
||||
private static class FunctionType extends BaseType {
|
||||
|
||||
Vector args;
|
||||
Vector<BaseType> args;
|
||||
String description;
|
||||
boolean packed;
|
||||
String returnType;
|
||||
@ -582,7 +582,7 @@ public class WrapperGenerator {
|
||||
|
||||
public FunctionType(String _desc)
|
||||
{
|
||||
args = new Vector();
|
||||
args = new Vector<>();
|
||||
description = _desc;
|
||||
setName(_desc);
|
||||
}
|
||||
@ -618,7 +618,7 @@ public class WrapperGenerator {
|
||||
return description;
|
||||
}
|
||||
|
||||
public Collection getArguments()
|
||||
public Collection<BaseType> getArguments()
|
||||
{
|
||||
return args;
|
||||
}
|
||||
@ -653,28 +653,28 @@ public class WrapperGenerator {
|
||||
public String getOffsets(StructType stp,AtomicType atp, boolean wide)
|
||||
{
|
||||
String key = stp.getName()+"."+atp.getName();
|
||||
return wide == true ? (String) sizeTable64bit.get(key) : (String) sizeTable32bit.get(key);
|
||||
return wide == true ? sizeTable64bit.get(key) : sizeTable32bit.get(key);
|
||||
}
|
||||
|
||||
public String getStructSize(StructType stp, boolean wide)
|
||||
{
|
||||
return wide == true ? (String) sizeTable64bit.get(stp.getName()) : (String) sizeTable32bit.get(stp.getName());
|
||||
return wide == true ? sizeTable64bit.get(stp.getName()) : sizeTable32bit.get(stp.getName());
|
||||
}
|
||||
|
||||
public int getLongSize(boolean wide)
|
||||
{
|
||||
return Integer.parseInt(wide == true ? (String)sizeTable64bit.get("long") : (String)sizeTable32bit.get("long"));
|
||||
return Integer.parseInt(wide == true ? sizeTable64bit.get("long") : sizeTable32bit.get("long"));
|
||||
}
|
||||
|
||||
public int getPtrSize(boolean wide)
|
||||
{
|
||||
return Integer.parseInt(wide == true ? (String)sizeTable64bit.get("ptr") : (String)sizeTable32bit.get("ptr"));
|
||||
return Integer.parseInt(wide == true ? sizeTable64bit.get("ptr") : sizeTable32bit.get("ptr"));
|
||||
}
|
||||
public int getBoolSize(boolean wide) {
|
||||
return getOrdinalSize("Bool", wide);
|
||||
}
|
||||
public int getOrdinalSize(String ordinal, boolean wide) {
|
||||
return Integer.parseInt(wide == true ? (String)sizeTable64bit.get(ordinal) : (String)sizeTable32bit.get(ordinal));
|
||||
return Integer.parseInt(wide == true ? sizeTable64bit.get(ordinal) : sizeTable32bit.get(ordinal));
|
||||
}
|
||||
|
||||
public void writeToString(StructType stp, PrintWriter pw) {
|
||||
@ -682,7 +682,7 @@ public class WrapperGenerator {
|
||||
pw.println("\n\n\tString getName() {\n\t\treturn \"" + stp.getName()+ "\"; \n\t}");
|
||||
pw.println("\n\n\tString getFieldsAsString() {\n\t\tStringBuilder ret = new StringBuilder(" + stp.getNumFields() * 40 + ");\n");
|
||||
|
||||
for (Enumeration e = stp.getMembers() ; e.hasMoreElements() ;) {
|
||||
for (Enumeration<BaseType> e = stp.getMembers() ; e.hasMoreElements() ;) {
|
||||
AtomicType tp = (AtomicType) e.nextElement();
|
||||
|
||||
type = tp.getType();
|
||||
@ -718,7 +718,7 @@ public class WrapperGenerator {
|
||||
} else {
|
||||
prefix = "\t";
|
||||
}
|
||||
for (Enumeration e = stp.getMembers() ; e.hasMoreElements() ;) {
|
||||
for (Enumeration<BaseType> e = stp.getMembers() ; e.hasMoreElements() ;) {
|
||||
AtomicType tp = (AtomicType) e.nextElement();
|
||||
|
||||
type = tp.getType();
|
||||
@ -753,7 +753,7 @@ public class WrapperGenerator {
|
||||
int acc_size_32 = 0;
|
||||
int acc_size_64 = 0;
|
||||
String s_log = (generateLog?"log.finest(\"\");":"");
|
||||
for (Enumeration e = stp.getMembers() ; e.hasMoreElements() ;) {
|
||||
for (Enumeration<BaseType> e = stp.getMembers() ; e.hasMoreElements() ;) {
|
||||
AtomicType tp = (AtomicType) e.nextElement();
|
||||
|
||||
type = tp.getType();
|
||||
@ -946,7 +946,7 @@ public class WrapperGenerator {
|
||||
pw.println("\tprivate static Unsafe unsafe = XlibWrapper.unsafe;");
|
||||
pw.println("\tprivate boolean __executed = false;");
|
||||
pw.println("\tprivate boolean __disposed = false;");
|
||||
Iterator iter = ft.getArguments().iterator();
|
||||
Iterator<BaseType> iter = ft.getArguments().iterator();
|
||||
while (iter.hasNext()) {
|
||||
AtomicType at = (AtomicType)iter.next();
|
||||
if (at.isIn()) {
|
||||
@ -1110,8 +1110,8 @@ public class WrapperGenerator {
|
||||
|
||||
public void writeJavaWrapperClass(String outputDir) {
|
||||
try {
|
||||
for (Enumeration e = symbolTable.elements() ; e.hasMoreElements() ;) {
|
||||
BaseType tp = (BaseType) e.nextElement();
|
||||
for (Enumeration<BaseType> e = symbolTable.elements() ; e.hasMoreElements() ;) {
|
||||
BaseType tp = e.nextElement();
|
||||
if (tp instanceof StructType) {
|
||||
StructType st = (StructType) tp;
|
||||
writeWrapper(outputDir, st);
|
||||
@ -1132,7 +1132,7 @@ public class WrapperGenerator {
|
||||
int j=0;
|
||||
BaseType tp;
|
||||
StructType stp;
|
||||
Enumeration eo;
|
||||
Enumeration<BaseType> eo;
|
||||
|
||||
try {
|
||||
|
||||
@ -1158,7 +1158,7 @@ public class WrapperGenerator {
|
||||
pw.println("\n\nint main(){");
|
||||
j=0;
|
||||
for ( eo = symbolTable.elements() ; eo.hasMoreElements() ;) {
|
||||
tp = (BaseType) eo.nextElement();
|
||||
tp = eo.nextElement();
|
||||
if (tp instanceof StructType)
|
||||
{
|
||||
stp = (StructType) tp;
|
||||
@ -1181,14 +1181,14 @@ public class WrapperGenerator {
|
||||
for (eo = symbolTable.elements() ; eo.hasMoreElements() ;) {
|
||||
|
||||
|
||||
tp = (BaseType) eo.nextElement();
|
||||
tp = eo.nextElement();
|
||||
if (tp instanceof StructType)
|
||||
{
|
||||
stp = (StructType) tp;
|
||||
if (stp.getIsInterface()) {
|
||||
continue;
|
||||
}
|
||||
for (Enumeration e = stp.getMembers() ; e.hasMoreElements() ;) {
|
||||
for (Enumeration<BaseType> e = stp.getMembers() ; e.hasMoreElements() ;) {
|
||||
AtomicType atp = (AtomicType) e.nextElement();
|
||||
if (atp.isAlias()) continue;
|
||||
pw.println("printf(\""+ stp.getName() + "." + atp.getName() + "\t%d\\n\""+
|
||||
@ -1277,7 +1277,7 @@ public class WrapperGenerator {
|
||||
|
||||
}
|
||||
else if (line != null) {
|
||||
BaseType bt = (BaseType) symbolTable.get(line);
|
||||
BaseType bt = symbolTable.get(line);
|
||||
if (bt == null) {
|
||||
if (line.startsWith("!")) {
|
||||
FunctionType ft = new FunctionType(line);
|
||||
|
@ -1,31 +0,0 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# 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 LauncherCommon.gmk
|
||||
|
||||
$(eval $(call SetupBuildLauncher, rmic, \
|
||||
MAIN_CLASS := sun.rmi.rmic.Main, \
|
||||
CFLAGS := -DEXPAND_CLASSPATH_WILDCARDS, \
|
||||
))
|
@ -144,7 +144,7 @@ define SetupBuildLauncherBody
|
||||
-DPROGNAME='"$1"' \
|
||||
$$($1_CFLAGS), \
|
||||
CFLAGS_linux := -fPIC, \
|
||||
CFLAGS_solaris := -KPIC -DHAVE_GETHRTIME, \
|
||||
CFLAGS_solaris := -KPIC, \
|
||||
CFLAGS_windows := $$($1_CFLAGS_windows), \
|
||||
DISABLED_WARNINGS_gcc := unused-function, \
|
||||
LDFLAGS := $$(LDFLAGS_JDKEXE) \
|
||||
|
@ -59,7 +59,8 @@ $(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHEREXE, \
|
||||
SRC := $(JPACKAGE_APPLAUNCHER_SRC), \
|
||||
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
|
||||
OPTIMIZATION := LOW, \
|
||||
CFLAGS := $(CXXFLAGS_JDKEXE), \
|
||||
CFLAGS := $(CFLAGS_JDKEXE), \
|
||||
CXXFLAGS := $(CXXFLAGS_JDKEXE), \
|
||||
CFLAGS_windows := -EHsc -DLAUNCHERC -DUNICODE -D_UNICODE, \
|
||||
LDFLAGS := $(LDFLAGS_JDKEXE), \
|
||||
LIBS_macosx := -framework Cocoa, \
|
||||
|
@ -260,7 +260,6 @@ module:jdk.naming.rmi
|
||||
module:jdk.net
|
||||
jdk.net
|
||||
jdk.nio
|
||||
module:jdk.rmic
|
||||
module:jdk.scripting.nashorn
|
||||
jdk.nashorn.api.scripting
|
||||
jdk.nashorn.api.tree
|
||||
|
@ -36,13 +36,15 @@ fi
|
||||
# Diff exceptions
|
||||
|
||||
if [ "$OPENJDK_TARGET_OS" = "linux" ]; then
|
||||
ACCEPTED_BIN_DIFF="
|
||||
./lib/server/libjvm.so
|
||||
./hotspot/gtest/server/libjvm.so
|
||||
"
|
||||
STRIP_BEFORE_COMPARE="
|
||||
./hotspot/gtest/server/libjvm.so
|
||||
"
|
||||
if [ "$HOTSPOT_BUILD_TIME" = "" -o "$USE_PRECOMPILED_HEADER" = "true" ]; then
|
||||
ACCEPTED_BIN_DIFF="
|
||||
./lib/server/libjvm.so
|
||||
./hotspot/gtest/server/libjvm.so
|
||||
"
|
||||
STRIP_BEFORE_COMPARE="
|
||||
./hotspot/gtest/server/libjvm.so
|
||||
"
|
||||
fi
|
||||
elif [ "$OPENJDK_TARGET_OS" = "solaris" ]; then
|
||||
SKIP_BIN_DIFF="true"
|
||||
SKIP_FULLDUMP_DIFF="true"
|
||||
|
@ -107,7 +107,8 @@ endif
|
||||
test:
|
||||
$(RM) -r $(RUN_DIR)
|
||||
$(MKDIR) -p $(RUN_DIR)
|
||||
$(CD) $(FH_BASEDIR)/test && JT_JAVA=$(BOOT_JDK) $(JTREGEXE) \
|
||||
$(CD) $(FH_BASEDIR)/test && $(JAVA) -Dprogram=jtreg \
|
||||
-jar $(JT_HOME)/lib/jtreg.jar \
|
||||
-jdk:$(BOOT_JDK) \
|
||||
$(JTREG_TEST_OPTS) \
|
||||
-timeout:0.1 -va -retain:all \
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2269,8 +2269,9 @@ public:
|
||||
#define INSN(NAME, opc, opc2, accepted) \
|
||||
void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn) { \
|
||||
guarantee(T != T1Q && T != T1D, "incorrect arrangement"); \
|
||||
if (accepted < 2) guarantee(T != T2S && T != T2D, "incorrect arrangement"); \
|
||||
if (accepted == 0) guarantee(T == T8B || T == T16B, "incorrect arrangement"); \
|
||||
if (accepted < 3) guarantee(T != T2D, "incorrect arrangement"); \
|
||||
if (accepted < 2) guarantee(T != T2S, "incorrect arrangement"); \
|
||||
if (accepted < 1) guarantee(T == T8B || T == T16B, "incorrect arrangement"); \
|
||||
starti; \
|
||||
f(0, 31), f((int)T & 1, 30), f(opc, 29), f(0b01110, 28, 24); \
|
||||
f((int)T >> 1, 23, 22), f(opc2, 21, 10); \
|
||||
@ -2278,12 +2279,13 @@ public:
|
||||
}
|
||||
|
||||
INSN(absr, 0, 0b100000101110, 1); // accepted arrangements: T8B, T16B, T4H, T8H, T4S
|
||||
INSN(negr, 1, 0b100000101110, 2); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
|
||||
INSN(negr, 1, 0b100000101110, 3); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D
|
||||
INSN(notr, 1, 0b100000010110, 0); // accepted arrangements: T8B, T16B
|
||||
INSN(addv, 0, 0b110001101110, 1); // accepted arrangements: T8B, T16B, T4H, T8H, T4S
|
||||
INSN(cls, 0, 0b100000010010, 1); // accepted arrangements: T8B, T16B, T4H, T8H, T4S
|
||||
INSN(clz, 1, 0b100000010010, 1); // accepted arrangements: T8B, T16B, T4H, T8H, T4S
|
||||
INSN(cnt, 0, 0b100000010110, 0); // accepted arrangements: T8B, T16B
|
||||
INSN(uaddlp, 1, 0b100000001010, 2); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S
|
||||
INSN(uaddlv, 1, 0b110000001110, 1); // accepted arrangements: T8B, T16B, T4H, T8H, T4S
|
||||
|
||||
#undef INSN
|
||||
|
@ -501,16 +501,13 @@ void LIR_Assembler::return_op(LIR_Opr result) {
|
||||
__ reserved_stack_check();
|
||||
}
|
||||
|
||||
address polling_page(os::get_polling_page());
|
||||
__ read_polling_page(rscratch1, polling_page, relocInfo::poll_return_type);
|
||||
__ fetch_and_read_polling_page(rscratch1, relocInfo::poll_return_type);
|
||||
__ ret(lr);
|
||||
}
|
||||
|
||||
int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) {
|
||||
address polling_page(os::get_polling_page());
|
||||
guarantee(info != NULL, "Shouldn't be NULL");
|
||||
assert(os::is_poll_address(polling_page), "should be");
|
||||
__ get_polling_page(rscratch1, polling_page, relocInfo::poll_type);
|
||||
__ get_polling_page(rscratch1, relocInfo::poll_type);
|
||||
add_debug_info_for_branch(info); // This isn't just debug info:
|
||||
// it's the oop map
|
||||
__ read_polling_page(rscratch1, relocInfo::poll_type);
|
||||
|
769
src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp
Normal file
769
src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp
Normal file
@ -0,0 +1,769 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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/assembler.hpp"
|
||||
#include "asm/assembler.inline.hpp"
|
||||
#include "opto/c2_MacroAssembler.hpp"
|
||||
#include "opto/intrinsicnode.hpp"
|
||||
|
||||
#ifdef PRODUCT
|
||||
#define BLOCK_COMMENT(str) /* nothing */
|
||||
#define STOP(error) stop(error)
|
||||
#else
|
||||
#define BLOCK_COMMENT(str) block_comment(str)
|
||||
#define STOP(error) block_comment(error); stop(error)
|
||||
#endif
|
||||
|
||||
#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
|
||||
|
||||
typedef void (MacroAssembler::* chr_insn)(Register Rt, const Address &adr);
|
||||
|
||||
// Search for str1 in str2 and return index or -1
|
||||
void C2_MacroAssembler::string_indexof(Register str2, Register str1,
|
||||
Register cnt2, Register cnt1,
|
||||
Register tmp1, Register tmp2,
|
||||
Register tmp3, Register tmp4,
|
||||
Register tmp5, Register tmp6,
|
||||
int icnt1, Register result, int ae) {
|
||||
// NOTE: tmp5, tmp6 can be zr depending on specific method version
|
||||
Label LINEARSEARCH, LINEARSTUB, LINEAR_MEDIUM, DONE, NOMATCH, MATCH;
|
||||
|
||||
Register ch1 = rscratch1;
|
||||
Register ch2 = rscratch2;
|
||||
Register cnt1tmp = tmp1;
|
||||
Register cnt2tmp = tmp2;
|
||||
Register cnt1_neg = cnt1;
|
||||
Register cnt2_neg = cnt2;
|
||||
Register result_tmp = tmp4;
|
||||
|
||||
bool isL = ae == StrIntrinsicNode::LL;
|
||||
|
||||
bool str1_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL;
|
||||
bool str2_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::LU;
|
||||
int str1_chr_shift = str1_isL ? 0:1;
|
||||
int str2_chr_shift = str2_isL ? 0:1;
|
||||
int str1_chr_size = str1_isL ? 1:2;
|
||||
int str2_chr_size = str2_isL ? 1:2;
|
||||
chr_insn str1_load_1chr = str1_isL ? (chr_insn)&MacroAssembler::ldrb :
|
||||
(chr_insn)&MacroAssembler::ldrh;
|
||||
chr_insn str2_load_1chr = str2_isL ? (chr_insn)&MacroAssembler::ldrb :
|
||||
(chr_insn)&MacroAssembler::ldrh;
|
||||
chr_insn load_2chr = isL ? (chr_insn)&MacroAssembler::ldrh : (chr_insn)&MacroAssembler::ldrw;
|
||||
chr_insn load_4chr = isL ? (chr_insn)&MacroAssembler::ldrw : (chr_insn)&MacroAssembler::ldr;
|
||||
|
||||
// Note, inline_string_indexOf() generates checks:
|
||||
// if (substr.count > string.count) return -1;
|
||||
// if (substr.count == 0) return 0;
|
||||
|
||||
// We have two strings, a source string in str2, cnt2 and a pattern string
|
||||
// in str1, cnt1. Find the 1st occurence of pattern in source or return -1.
|
||||
|
||||
// For larger pattern and source we use a simplified Boyer Moore algorithm.
|
||||
// With a small pattern and source we use linear scan.
|
||||
|
||||
if (icnt1 == -1) {
|
||||
sub(result_tmp, cnt2, cnt1);
|
||||
cmp(cnt1, (u1)8); // Use Linear Scan if cnt1 < 8 || cnt1 >= 256
|
||||
br(LT, LINEARSEARCH);
|
||||
dup(v0, T16B, cnt1); // done in separate FPU pipeline. Almost no penalty
|
||||
subs(zr, cnt1, 256);
|
||||
lsr(tmp1, cnt2, 2);
|
||||
ccmp(cnt1, tmp1, 0b0000, LT); // Source must be 4 * pattern for BM
|
||||
br(GE, LINEARSTUB);
|
||||
}
|
||||
|
||||
// The Boyer Moore alogorithm is based on the description here:-
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm
|
||||
//
|
||||
// This describes and algorithm with 2 shift rules. The 'Bad Character' rule
|
||||
// and the 'Good Suffix' rule.
|
||||
//
|
||||
// These rules are essentially heuristics for how far we can shift the
|
||||
// pattern along the search string.
|
||||
//
|
||||
// The implementation here uses the 'Bad Character' rule only because of the
|
||||
// complexity of initialisation for the 'Good Suffix' rule.
|
||||
//
|
||||
// This is also known as the Boyer-Moore-Horspool algorithm:-
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Boyer-Moore-Horspool_algorithm
|
||||
//
|
||||
// This particular implementation has few java-specific optimizations.
|
||||
//
|
||||
// #define ASIZE 256
|
||||
//
|
||||
// int bm(unsigned char *x, int m, unsigned char *y, int n) {
|
||||
// int i, j;
|
||||
// unsigned c;
|
||||
// unsigned char bc[ASIZE];
|
||||
//
|
||||
// /* Preprocessing */
|
||||
// for (i = 0; i < ASIZE; ++i)
|
||||
// bc[i] = m;
|
||||
// for (i = 0; i < m - 1; ) {
|
||||
// c = x[i];
|
||||
// ++i;
|
||||
// // c < 256 for Latin1 string, so, no need for branch
|
||||
// #ifdef PATTERN_STRING_IS_LATIN1
|
||||
// bc[c] = m - i;
|
||||
// #else
|
||||
// if (c < ASIZE) bc[c] = m - i;
|
||||
// #endif
|
||||
// }
|
||||
//
|
||||
// /* Searching */
|
||||
// j = 0;
|
||||
// while (j <= n - m) {
|
||||
// c = y[i+j];
|
||||
// if (x[m-1] == c)
|
||||
// for (i = m - 2; i >= 0 && x[i] == y[i + j]; --i);
|
||||
// if (i < 0) return j;
|
||||
// // c < 256 for Latin1 string, so, no need for branch
|
||||
// #ifdef SOURCE_STRING_IS_LATIN1
|
||||
// // LL case: (c< 256) always true. Remove branch
|
||||
// j += bc[y[j+m-1]];
|
||||
// #endif
|
||||
// #ifndef PATTERN_STRING_IS_UTF
|
||||
// // UU case: need if (c<ASIZE) check. Skip 1 character if not.
|
||||
// if (c < ASIZE)
|
||||
// j += bc[y[j+m-1]];
|
||||
// else
|
||||
// j += 1
|
||||
// #endif
|
||||
// #ifdef PATTERN_IS_LATIN1_AND_SOURCE_IS_UTF
|
||||
// // UL case: need if (c<ASIZE) check. Skip <pattern length> if not.
|
||||
// if (c < ASIZE)
|
||||
// j += bc[y[j+m-1]];
|
||||
// else
|
||||
// j += m
|
||||
// #endif
|
||||
// }
|
||||
// }
|
||||
|
||||
if (icnt1 == -1) {
|
||||
Label BCLOOP, BCSKIP, BMLOOPSTR2, BMLOOPSTR1, BMSKIP, BMADV, BMMATCH,
|
||||
BMLOOPSTR1_LASTCMP, BMLOOPSTR1_CMP, BMLOOPSTR1_AFTER_LOAD, BM_INIT_LOOP;
|
||||
Register cnt1end = tmp2;
|
||||
Register str2end = cnt2;
|
||||
Register skipch = tmp2;
|
||||
|
||||
// str1 length is >=8, so, we can read at least 1 register for cases when
|
||||
// UTF->Latin1 conversion is not needed(8 LL or 4UU) and half register for
|
||||
// UL case. We'll re-read last character in inner pre-loop code to have
|
||||
// single outer pre-loop load
|
||||
const int firstStep = isL ? 7 : 3;
|
||||
|
||||
const int ASIZE = 256;
|
||||
const int STORED_BYTES = 32; // amount of bytes stored per instruction
|
||||
sub(sp, sp, ASIZE);
|
||||
mov(tmp5, ASIZE/STORED_BYTES); // loop iterations
|
||||
mov(ch1, sp);
|
||||
BIND(BM_INIT_LOOP);
|
||||
stpq(v0, v0, Address(post(ch1, STORED_BYTES)));
|
||||
subs(tmp5, tmp5, 1);
|
||||
br(GT, BM_INIT_LOOP);
|
||||
|
||||
sub(cnt1tmp, cnt1, 1);
|
||||
mov(tmp5, str2);
|
||||
add(str2end, str2, result_tmp, LSL, str2_chr_shift);
|
||||
sub(ch2, cnt1, 1);
|
||||
mov(tmp3, str1);
|
||||
BIND(BCLOOP);
|
||||
(this->*str1_load_1chr)(ch1, Address(post(tmp3, str1_chr_size)));
|
||||
if (!str1_isL) {
|
||||
subs(zr, ch1, ASIZE);
|
||||
br(HS, BCSKIP);
|
||||
}
|
||||
strb(ch2, Address(sp, ch1));
|
||||
BIND(BCSKIP);
|
||||
subs(ch2, ch2, 1);
|
||||
br(GT, BCLOOP);
|
||||
|
||||
add(tmp6, str1, cnt1, LSL, str1_chr_shift); // address after str1
|
||||
if (str1_isL == str2_isL) {
|
||||
// load last 8 bytes (8LL/4UU symbols)
|
||||
ldr(tmp6, Address(tmp6, -wordSize));
|
||||
} else {
|
||||
ldrw(tmp6, Address(tmp6, -wordSize/2)); // load last 4 bytes(4 symbols)
|
||||
// convert Latin1 to UTF. We'll have to wait until load completed, but
|
||||
// it's still faster than per-character loads+checks
|
||||
lsr(tmp3, tmp6, BitsPerByte * (wordSize/2 - str1_chr_size)); // str1[N-1]
|
||||
ubfx(ch1, tmp6, 8, 8); // str1[N-2]
|
||||
ubfx(ch2, tmp6, 16, 8); // str1[N-3]
|
||||
andr(tmp6, tmp6, 0xFF); // str1[N-4]
|
||||
orr(ch2, ch1, ch2, LSL, 16);
|
||||
orr(tmp6, tmp6, tmp3, LSL, 48);
|
||||
orr(tmp6, tmp6, ch2, LSL, 16);
|
||||
}
|
||||
BIND(BMLOOPSTR2);
|
||||
(this->*str2_load_1chr)(skipch, Address(str2, cnt1tmp, Address::lsl(str2_chr_shift)));
|
||||
sub(cnt1tmp, cnt1tmp, firstStep); // cnt1tmp is positive here, because cnt1 >= 8
|
||||
if (str1_isL == str2_isL) {
|
||||
// re-init tmp3. It's for free because it's executed in parallel with
|
||||
// load above. Alternative is to initialize it before loop, but it'll
|
||||
// affect performance on in-order systems with 2 or more ld/st pipelines
|
||||
lsr(tmp3, tmp6, BitsPerByte * (wordSize - str1_chr_size));
|
||||
}
|
||||
if (!isL) { // UU/UL case
|
||||
lsl(ch2, cnt1tmp, 1); // offset in bytes
|
||||
}
|
||||
cmp(tmp3, skipch);
|
||||
br(NE, BMSKIP);
|
||||
ldr(ch2, Address(str2, isL ? cnt1tmp : ch2));
|
||||
mov(ch1, tmp6);
|
||||
if (isL) {
|
||||
b(BMLOOPSTR1_AFTER_LOAD);
|
||||
} else {
|
||||
sub(cnt1tmp, cnt1tmp, 1); // no need to branch for UU/UL case. cnt1 >= 8
|
||||
b(BMLOOPSTR1_CMP);
|
||||
}
|
||||
BIND(BMLOOPSTR1);
|
||||
(this->*str1_load_1chr)(ch1, Address(str1, cnt1tmp, Address::lsl(str1_chr_shift)));
|
||||
(this->*str2_load_1chr)(ch2, Address(str2, cnt1tmp, Address::lsl(str2_chr_shift)));
|
||||
BIND(BMLOOPSTR1_AFTER_LOAD);
|
||||
subs(cnt1tmp, cnt1tmp, 1);
|
||||
br(LT, BMLOOPSTR1_LASTCMP);
|
||||
BIND(BMLOOPSTR1_CMP);
|
||||
cmp(ch1, ch2);
|
||||
br(EQ, BMLOOPSTR1);
|
||||
BIND(BMSKIP);
|
||||
if (!isL) {
|
||||
// if we've met UTF symbol while searching Latin1 pattern, then we can
|
||||
// skip cnt1 symbols
|
||||
if (str1_isL != str2_isL) {
|
||||
mov(result_tmp, cnt1);
|
||||
} else {
|
||||
mov(result_tmp, 1);
|
||||
}
|
||||
subs(zr, skipch, ASIZE);
|
||||
br(HS, BMADV);
|
||||
}
|
||||
ldrb(result_tmp, Address(sp, skipch)); // load skip distance
|
||||
BIND(BMADV);
|
||||
sub(cnt1tmp, cnt1, 1);
|
||||
add(str2, str2, result_tmp, LSL, str2_chr_shift);
|
||||
cmp(str2, str2end);
|
||||
br(LE, BMLOOPSTR2);
|
||||
add(sp, sp, ASIZE);
|
||||
b(NOMATCH);
|
||||
BIND(BMLOOPSTR1_LASTCMP);
|
||||
cmp(ch1, ch2);
|
||||
br(NE, BMSKIP);
|
||||
BIND(BMMATCH);
|
||||
sub(result, str2, tmp5);
|
||||
if (!str2_isL) lsr(result, result, 1);
|
||||
add(sp, sp, ASIZE);
|
||||
b(DONE);
|
||||
|
||||
BIND(LINEARSTUB);
|
||||
cmp(cnt1, (u1)16); // small patterns still should be handled by simple algorithm
|
||||
br(LT, LINEAR_MEDIUM);
|
||||
mov(result, zr);
|
||||
RuntimeAddress stub = NULL;
|
||||
if (isL) {
|
||||
stub = RuntimeAddress(StubRoutines::aarch64::string_indexof_linear_ll());
|
||||
assert(stub.target() != NULL, "string_indexof_linear_ll stub has not been generated");
|
||||
} else if (str1_isL) {
|
||||
stub = RuntimeAddress(StubRoutines::aarch64::string_indexof_linear_ul());
|
||||
assert(stub.target() != NULL, "string_indexof_linear_ul stub has not been generated");
|
||||
} else {
|
||||
stub = RuntimeAddress(StubRoutines::aarch64::string_indexof_linear_uu());
|
||||
assert(stub.target() != NULL, "string_indexof_linear_uu stub has not been generated");
|
||||
}
|
||||
trampoline_call(stub);
|
||||
b(DONE);
|
||||
}
|
||||
|
||||
BIND(LINEARSEARCH);
|
||||
{
|
||||
Label DO1, DO2, DO3;
|
||||
|
||||
Register str2tmp = tmp2;
|
||||
Register first = tmp3;
|
||||
|
||||
if (icnt1 == -1)
|
||||
{
|
||||
Label DOSHORT, FIRST_LOOP, STR2_NEXT, STR1_LOOP, STR1_NEXT;
|
||||
|
||||
cmp(cnt1, u1(str1_isL == str2_isL ? 4 : 2));
|
||||
br(LT, DOSHORT);
|
||||
BIND(LINEAR_MEDIUM);
|
||||
(this->*str1_load_1chr)(first, Address(str1));
|
||||
lea(str1, Address(str1, cnt1, Address::lsl(str1_chr_shift)));
|
||||
sub(cnt1_neg, zr, cnt1, LSL, str1_chr_shift);
|
||||
lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
|
||||
sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
|
||||
|
||||
BIND(FIRST_LOOP);
|
||||
(this->*str2_load_1chr)(ch2, Address(str2, cnt2_neg));
|
||||
cmp(first, ch2);
|
||||
br(EQ, STR1_LOOP);
|
||||
BIND(STR2_NEXT);
|
||||
adds(cnt2_neg, cnt2_neg, str2_chr_size);
|
||||
br(LE, FIRST_LOOP);
|
||||
b(NOMATCH);
|
||||
|
||||
BIND(STR1_LOOP);
|
||||
adds(cnt1tmp, cnt1_neg, str1_chr_size);
|
||||
add(cnt2tmp, cnt2_neg, str2_chr_size);
|
||||
br(GE, MATCH);
|
||||
|
||||
BIND(STR1_NEXT);
|
||||
(this->*str1_load_1chr)(ch1, Address(str1, cnt1tmp));
|
||||
(this->*str2_load_1chr)(ch2, Address(str2, cnt2tmp));
|
||||
cmp(ch1, ch2);
|
||||
br(NE, STR2_NEXT);
|
||||
adds(cnt1tmp, cnt1tmp, str1_chr_size);
|
||||
add(cnt2tmp, cnt2tmp, str2_chr_size);
|
||||
br(LT, STR1_NEXT);
|
||||
b(MATCH);
|
||||
|
||||
BIND(DOSHORT);
|
||||
if (str1_isL == str2_isL) {
|
||||
cmp(cnt1, (u1)2);
|
||||
br(LT, DO1);
|
||||
br(GT, DO3);
|
||||
}
|
||||
}
|
||||
|
||||
if (icnt1 == 4) {
|
||||
Label CH1_LOOP;
|
||||
|
||||
(this->*load_4chr)(ch1, str1);
|
||||
sub(result_tmp, cnt2, 4);
|
||||
lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
|
||||
sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
|
||||
|
||||
BIND(CH1_LOOP);
|
||||
(this->*load_4chr)(ch2, Address(str2, cnt2_neg));
|
||||
cmp(ch1, ch2);
|
||||
br(EQ, MATCH);
|
||||
adds(cnt2_neg, cnt2_neg, str2_chr_size);
|
||||
br(LE, CH1_LOOP);
|
||||
b(NOMATCH);
|
||||
}
|
||||
|
||||
if ((icnt1 == -1 && str1_isL == str2_isL) || icnt1 == 2) {
|
||||
Label CH1_LOOP;
|
||||
|
||||
BIND(DO2);
|
||||
(this->*load_2chr)(ch1, str1);
|
||||
if (icnt1 == 2) {
|
||||
sub(result_tmp, cnt2, 2);
|
||||
}
|
||||
lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
|
||||
sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
|
||||
BIND(CH1_LOOP);
|
||||
(this->*load_2chr)(ch2, Address(str2, cnt2_neg));
|
||||
cmp(ch1, ch2);
|
||||
br(EQ, MATCH);
|
||||
adds(cnt2_neg, cnt2_neg, str2_chr_size);
|
||||
br(LE, CH1_LOOP);
|
||||
b(NOMATCH);
|
||||
}
|
||||
|
||||
if ((icnt1 == -1 && str1_isL == str2_isL) || icnt1 == 3) {
|
||||
Label FIRST_LOOP, STR2_NEXT, STR1_LOOP;
|
||||
|
||||
BIND(DO3);
|
||||
(this->*load_2chr)(first, str1);
|
||||
(this->*str1_load_1chr)(ch1, Address(str1, 2*str1_chr_size));
|
||||
if (icnt1 == 3) {
|
||||
sub(result_tmp, cnt2, 3);
|
||||
}
|
||||
lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
|
||||
sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
|
||||
BIND(FIRST_LOOP);
|
||||
(this->*load_2chr)(ch2, Address(str2, cnt2_neg));
|
||||
cmpw(first, ch2);
|
||||
br(EQ, STR1_LOOP);
|
||||
BIND(STR2_NEXT);
|
||||
adds(cnt2_neg, cnt2_neg, str2_chr_size);
|
||||
br(LE, FIRST_LOOP);
|
||||
b(NOMATCH);
|
||||
|
||||
BIND(STR1_LOOP);
|
||||
add(cnt2tmp, cnt2_neg, 2*str2_chr_size);
|
||||
(this->*str2_load_1chr)(ch2, Address(str2, cnt2tmp));
|
||||
cmp(ch1, ch2);
|
||||
br(NE, STR2_NEXT);
|
||||
b(MATCH);
|
||||
}
|
||||
|
||||
if (icnt1 == -1 || icnt1 == 1) {
|
||||
Label CH1_LOOP, HAS_ZERO, DO1_SHORT, DO1_LOOP;
|
||||
|
||||
BIND(DO1);
|
||||
(this->*str1_load_1chr)(ch1, str1);
|
||||
cmp(cnt2, (u1)8);
|
||||
br(LT, DO1_SHORT);
|
||||
|
||||
sub(result_tmp, cnt2, 8/str2_chr_size);
|
||||
sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
|
||||
mov(tmp3, str2_isL ? 0x0101010101010101 : 0x0001000100010001);
|
||||
lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
|
||||
|
||||
if (str2_isL) {
|
||||
orr(ch1, ch1, ch1, LSL, 8);
|
||||
}
|
||||
orr(ch1, ch1, ch1, LSL, 16);
|
||||
orr(ch1, ch1, ch1, LSL, 32);
|
||||
BIND(CH1_LOOP);
|
||||
ldr(ch2, Address(str2, cnt2_neg));
|
||||
eor(ch2, ch1, ch2);
|
||||
sub(tmp1, ch2, tmp3);
|
||||
orr(tmp2, ch2, str2_isL ? 0x7f7f7f7f7f7f7f7f : 0x7fff7fff7fff7fff);
|
||||
bics(tmp1, tmp1, tmp2);
|
||||
br(NE, HAS_ZERO);
|
||||
adds(cnt2_neg, cnt2_neg, 8);
|
||||
br(LT, CH1_LOOP);
|
||||
|
||||
cmp(cnt2_neg, (u1)8);
|
||||
mov(cnt2_neg, 0);
|
||||
br(LT, CH1_LOOP);
|
||||
b(NOMATCH);
|
||||
|
||||
BIND(HAS_ZERO);
|
||||
rev(tmp1, tmp1);
|
||||
clz(tmp1, tmp1);
|
||||
add(cnt2_neg, cnt2_neg, tmp1, LSR, 3);
|
||||
b(MATCH);
|
||||
|
||||
BIND(DO1_SHORT);
|
||||
mov(result_tmp, cnt2);
|
||||
lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
|
||||
sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
|
||||
BIND(DO1_LOOP);
|
||||
(this->*str2_load_1chr)(ch2, Address(str2, cnt2_neg));
|
||||
cmpw(ch1, ch2);
|
||||
br(EQ, MATCH);
|
||||
adds(cnt2_neg, cnt2_neg, str2_chr_size);
|
||||
br(LT, DO1_LOOP);
|
||||
}
|
||||
}
|
||||
BIND(NOMATCH);
|
||||
mov(result, -1);
|
||||
b(DONE);
|
||||
BIND(MATCH);
|
||||
add(result, result_tmp, cnt2_neg, ASR, str2_chr_shift);
|
||||
BIND(DONE);
|
||||
}
|
||||
|
||||
typedef void (MacroAssembler::* chr_insn)(Register Rt, const Address &adr);
|
||||
typedef void (MacroAssembler::* uxt_insn)(Register Rd, Register Rn);
|
||||
|
||||
void C2_MacroAssembler::string_indexof_char(Register str1, Register cnt1,
|
||||
Register ch, Register result,
|
||||
Register tmp1, Register tmp2, Register tmp3)
|
||||
{
|
||||
Label CH1_LOOP, HAS_ZERO, DO1_SHORT, DO1_LOOP, MATCH, NOMATCH, DONE;
|
||||
Register cnt1_neg = cnt1;
|
||||
Register ch1 = rscratch1;
|
||||
Register result_tmp = rscratch2;
|
||||
|
||||
cbz(cnt1, NOMATCH);
|
||||
|
||||
cmp(cnt1, (u1)4);
|
||||
br(LT, DO1_SHORT);
|
||||
|
||||
orr(ch, ch, ch, LSL, 16);
|
||||
orr(ch, ch, ch, LSL, 32);
|
||||
|
||||
sub(cnt1, cnt1, 4);
|
||||
mov(result_tmp, cnt1);
|
||||
lea(str1, Address(str1, cnt1, Address::uxtw(1)));
|
||||
sub(cnt1_neg, zr, cnt1, LSL, 1);
|
||||
|
||||
mov(tmp3, 0x0001000100010001);
|
||||
|
||||
BIND(CH1_LOOP);
|
||||
ldr(ch1, Address(str1, cnt1_neg));
|
||||
eor(ch1, ch, ch1);
|
||||
sub(tmp1, ch1, tmp3);
|
||||
orr(tmp2, ch1, 0x7fff7fff7fff7fff);
|
||||
bics(tmp1, tmp1, tmp2);
|
||||
br(NE, HAS_ZERO);
|
||||
adds(cnt1_neg, cnt1_neg, 8);
|
||||
br(LT, CH1_LOOP);
|
||||
|
||||
cmp(cnt1_neg, (u1)8);
|
||||
mov(cnt1_neg, 0);
|
||||
br(LT, CH1_LOOP);
|
||||
b(NOMATCH);
|
||||
|
||||
BIND(HAS_ZERO);
|
||||
rev(tmp1, tmp1);
|
||||
clz(tmp1, tmp1);
|
||||
add(cnt1_neg, cnt1_neg, tmp1, LSR, 3);
|
||||
b(MATCH);
|
||||
|
||||
BIND(DO1_SHORT);
|
||||
mov(result_tmp, cnt1);
|
||||
lea(str1, Address(str1, cnt1, Address::uxtw(1)));
|
||||
sub(cnt1_neg, zr, cnt1, LSL, 1);
|
||||
BIND(DO1_LOOP);
|
||||
ldrh(ch1, Address(str1, cnt1_neg));
|
||||
cmpw(ch, ch1);
|
||||
br(EQ, MATCH);
|
||||
adds(cnt1_neg, cnt1_neg, 2);
|
||||
br(LT, DO1_LOOP);
|
||||
BIND(NOMATCH);
|
||||
mov(result, -1);
|
||||
b(DONE);
|
||||
BIND(MATCH);
|
||||
add(result, result_tmp, cnt1_neg, ASR, 1);
|
||||
BIND(DONE);
|
||||
}
|
||||
|
||||
// Compare strings.
|
||||
void C2_MacroAssembler::string_compare(Register str1, Register str2,
|
||||
Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2,
|
||||
FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3, int ae) {
|
||||
Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB,
|
||||
DIFFERENCE, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT,
|
||||
SHORT_LOOP_START, TAIL_CHECK;
|
||||
|
||||
bool isLL = ae == StrIntrinsicNode::LL;
|
||||
bool isLU = ae == StrIntrinsicNode::LU;
|
||||
bool isUL = ae == StrIntrinsicNode::UL;
|
||||
|
||||
// The stub threshold for LL strings is: 72 (64 + 8) chars
|
||||
// UU: 36 chars, or 72 bytes (valid for the 64-byte large loop with prefetch)
|
||||
// LU/UL: 24 chars, or 48 bytes (valid for the 16-character loop at least)
|
||||
const u1 stub_threshold = isLL ? 72 : ((isLU || isUL) ? 24 : 36);
|
||||
|
||||
bool str1_isL = isLL || isLU;
|
||||
bool str2_isL = isLL || isUL;
|
||||
|
||||
int str1_chr_shift = str1_isL ? 0 : 1;
|
||||
int str2_chr_shift = str2_isL ? 0 : 1;
|
||||
int str1_chr_size = str1_isL ? 1 : 2;
|
||||
int str2_chr_size = str2_isL ? 1 : 2;
|
||||
int minCharsInWord = isLL ? wordSize : wordSize/2;
|
||||
|
||||
FloatRegister vtmpZ = vtmp1, vtmp = vtmp2;
|
||||
chr_insn str1_load_chr = str1_isL ? (chr_insn)&MacroAssembler::ldrb :
|
||||
(chr_insn)&MacroAssembler::ldrh;
|
||||
chr_insn str2_load_chr = str2_isL ? (chr_insn)&MacroAssembler::ldrb :
|
||||
(chr_insn)&MacroAssembler::ldrh;
|
||||
uxt_insn ext_chr = isLL ? (uxt_insn)&MacroAssembler::uxtbw :
|
||||
(uxt_insn)&MacroAssembler::uxthw;
|
||||
|
||||
BLOCK_COMMENT("string_compare {");
|
||||
|
||||
// Bizzarely, the counts are passed in bytes, regardless of whether they
|
||||
// are L or U strings, however the result is always in characters.
|
||||
if (!str1_isL) asrw(cnt1, cnt1, 1);
|
||||
if (!str2_isL) asrw(cnt2, cnt2, 1);
|
||||
|
||||
// Compute the minimum of the string lengths and save the difference.
|
||||
subsw(result, cnt1, cnt2);
|
||||
cselw(cnt2, cnt1, cnt2, Assembler::LE); // min
|
||||
|
||||
// A very short string
|
||||
cmpw(cnt2, minCharsInWord);
|
||||
br(Assembler::LE, SHORT_STRING);
|
||||
|
||||
// Compare longwords
|
||||
// load first parts of strings and finish initialization while loading
|
||||
{
|
||||
if (str1_isL == str2_isL) { // LL or UU
|
||||
ldr(tmp1, Address(str1));
|
||||
cmp(str1, str2);
|
||||
br(Assembler::EQ, DONE);
|
||||
ldr(tmp2, Address(str2));
|
||||
cmp(cnt2, stub_threshold);
|
||||
br(GE, STUB);
|
||||
subsw(cnt2, cnt2, minCharsInWord);
|
||||
br(EQ, TAIL_CHECK);
|
||||
lea(str2, Address(str2, cnt2, Address::uxtw(str2_chr_shift)));
|
||||
lea(str1, Address(str1, cnt2, Address::uxtw(str1_chr_shift)));
|
||||
sub(cnt2, zr, cnt2, LSL, str2_chr_shift);
|
||||
} else if (isLU) {
|
||||
ldrs(vtmp, Address(str1));
|
||||
ldr(tmp2, Address(str2));
|
||||
cmp(cnt2, stub_threshold);
|
||||
br(GE, STUB);
|
||||
subw(cnt2, cnt2, 4);
|
||||
eor(vtmpZ, T16B, vtmpZ, vtmpZ);
|
||||
lea(str1, Address(str1, cnt2, Address::uxtw(str1_chr_shift)));
|
||||
lea(str2, Address(str2, cnt2, Address::uxtw(str2_chr_shift)));
|
||||
zip1(vtmp, T8B, vtmp, vtmpZ);
|
||||
sub(cnt1, zr, cnt2, LSL, str1_chr_shift);
|
||||
sub(cnt2, zr, cnt2, LSL, str2_chr_shift);
|
||||
add(cnt1, cnt1, 4);
|
||||
fmovd(tmp1, vtmp);
|
||||
} else { // UL case
|
||||
ldr(tmp1, Address(str1));
|
||||
ldrs(vtmp, Address(str2));
|
||||
cmp(cnt2, stub_threshold);
|
||||
br(GE, STUB);
|
||||
subw(cnt2, cnt2, 4);
|
||||
lea(str1, Address(str1, cnt2, Address::uxtw(str1_chr_shift)));
|
||||
eor(vtmpZ, T16B, vtmpZ, vtmpZ);
|
||||
lea(str2, Address(str2, cnt2, Address::uxtw(str2_chr_shift)));
|
||||
sub(cnt1, zr, cnt2, LSL, str1_chr_shift);
|
||||
zip1(vtmp, T8B, vtmp, vtmpZ);
|
||||
sub(cnt2, zr, cnt2, LSL, str2_chr_shift);
|
||||
add(cnt1, cnt1, 8);
|
||||
fmovd(tmp2, vtmp);
|
||||
}
|
||||
adds(cnt2, cnt2, isUL ? 4 : 8);
|
||||
br(GE, TAIL);
|
||||
eor(rscratch2, tmp1, tmp2);
|
||||
cbnz(rscratch2, DIFFERENCE);
|
||||
// main loop
|
||||
bind(NEXT_WORD);
|
||||
if (str1_isL == str2_isL) {
|
||||
ldr(tmp1, Address(str1, cnt2));
|
||||
ldr(tmp2, Address(str2, cnt2));
|
||||
adds(cnt2, cnt2, 8);
|
||||
} else if (isLU) {
|
||||
ldrs(vtmp, Address(str1, cnt1));
|
||||
ldr(tmp2, Address(str2, cnt2));
|
||||
add(cnt1, cnt1, 4);
|
||||
zip1(vtmp, T8B, vtmp, vtmpZ);
|
||||
fmovd(tmp1, vtmp);
|
||||
adds(cnt2, cnt2, 8);
|
||||
} else { // UL
|
||||
ldrs(vtmp, Address(str2, cnt2));
|
||||
ldr(tmp1, Address(str1, cnt1));
|
||||
zip1(vtmp, T8B, vtmp, vtmpZ);
|
||||
add(cnt1, cnt1, 8);
|
||||
fmovd(tmp2, vtmp);
|
||||
adds(cnt2, cnt2, 4);
|
||||
}
|
||||
br(GE, TAIL);
|
||||
|
||||
eor(rscratch2, tmp1, tmp2);
|
||||
cbz(rscratch2, NEXT_WORD);
|
||||
b(DIFFERENCE);
|
||||
bind(TAIL);
|
||||
eor(rscratch2, tmp1, tmp2);
|
||||
cbnz(rscratch2, DIFFERENCE);
|
||||
// Last longword. In the case where length == 4 we compare the
|
||||
// same longword twice, but that's still faster than another
|
||||
// conditional branch.
|
||||
if (str1_isL == str2_isL) {
|
||||
ldr(tmp1, Address(str1));
|
||||
ldr(tmp2, Address(str2));
|
||||
} else if (isLU) {
|
||||
ldrs(vtmp, Address(str1));
|
||||
ldr(tmp2, Address(str2));
|
||||
zip1(vtmp, T8B, vtmp, vtmpZ);
|
||||
fmovd(tmp1, vtmp);
|
||||
} else { // UL
|
||||
ldrs(vtmp, Address(str2));
|
||||
ldr(tmp1, Address(str1));
|
||||
zip1(vtmp, T8B, vtmp, vtmpZ);
|
||||
fmovd(tmp2, vtmp);
|
||||
}
|
||||
bind(TAIL_CHECK);
|
||||
eor(rscratch2, tmp1, tmp2);
|
||||
cbz(rscratch2, DONE);
|
||||
|
||||
// Find the first different characters in the longwords and
|
||||
// compute their difference.
|
||||
bind(DIFFERENCE);
|
||||
rev(rscratch2, rscratch2);
|
||||
clz(rscratch2, rscratch2);
|
||||
andr(rscratch2, rscratch2, isLL ? -8 : -16);
|
||||
lsrv(tmp1, tmp1, rscratch2);
|
||||
(this->*ext_chr)(tmp1, tmp1);
|
||||
lsrv(tmp2, tmp2, rscratch2);
|
||||
(this->*ext_chr)(tmp2, tmp2);
|
||||
subw(result, tmp1, tmp2);
|
||||
b(DONE);
|
||||
}
|
||||
|
||||
bind(STUB);
|
||||
RuntimeAddress stub = NULL;
|
||||
switch(ae) {
|
||||
case StrIntrinsicNode::LL:
|
||||
stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_LL());
|
||||
break;
|
||||
case StrIntrinsicNode::UU:
|
||||
stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_UU());
|
||||
break;
|
||||
case StrIntrinsicNode::LU:
|
||||
stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_LU());
|
||||
break;
|
||||
case StrIntrinsicNode::UL:
|
||||
stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_UL());
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
assert(stub.target() != NULL, "compare_long_string stub has not been generated");
|
||||
trampoline_call(stub);
|
||||
b(DONE);
|
||||
|
||||
bind(SHORT_STRING);
|
||||
// Is the minimum length zero?
|
||||
cbz(cnt2, DONE);
|
||||
// arrange code to do most branches while loading and loading next characters
|
||||
// while comparing previous
|
||||
(this->*str1_load_chr)(tmp1, Address(post(str1, str1_chr_size)));
|
||||
subs(cnt2, cnt2, 1);
|
||||
br(EQ, SHORT_LAST_INIT);
|
||||
(this->*str2_load_chr)(cnt1, Address(post(str2, str2_chr_size)));
|
||||
b(SHORT_LOOP_START);
|
||||
bind(SHORT_LOOP);
|
||||
subs(cnt2, cnt2, 1);
|
||||
br(EQ, SHORT_LAST);
|
||||
bind(SHORT_LOOP_START);
|
||||
(this->*str1_load_chr)(tmp2, Address(post(str1, str1_chr_size)));
|
||||
(this->*str2_load_chr)(rscratch1, Address(post(str2, str2_chr_size)));
|
||||
cmp(tmp1, cnt1);
|
||||
br(NE, SHORT_LOOP_TAIL);
|
||||
subs(cnt2, cnt2, 1);
|
||||
br(EQ, SHORT_LAST2);
|
||||
(this->*str1_load_chr)(tmp1, Address(post(str1, str1_chr_size)));
|
||||
(this->*str2_load_chr)(cnt1, Address(post(str2, str2_chr_size)));
|
||||
cmp(tmp2, rscratch1);
|
||||
br(EQ, SHORT_LOOP);
|
||||
sub(result, tmp2, rscratch1);
|
||||
b(DONE);
|
||||
bind(SHORT_LOOP_TAIL);
|
||||
sub(result, tmp1, cnt1);
|
||||
b(DONE);
|
||||
bind(SHORT_LAST2);
|
||||
cmp(tmp2, rscratch1);
|
||||
br(EQ, DONE);
|
||||
sub(result, tmp2, rscratch1);
|
||||
|
||||
b(DONE);
|
||||
bind(SHORT_LAST_INIT);
|
||||
(this->*str2_load_chr)(cnt1, Address(post(str2, str2_chr_size)));
|
||||
bind(SHORT_LAST);
|
||||
cmp(tmp1, cnt1);
|
||||
br(EQ, DONE);
|
||||
sub(result, tmp1, cnt1);
|
||||
|
||||
bind(DONE);
|
||||
|
||||
BLOCK_COMMENT("} string_compare");
|
||||
}
|
48
src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp
Normal file
48
src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CPU_AARCH64_C2_MACROASSEMBLER_AARCH64_HPP
|
||||
#define CPU_AARCH64_C2_MACROASSEMBLER_AARCH64_HPP
|
||||
|
||||
// C2_MacroAssembler contains high-level macros for C2
|
||||
|
||||
public:
|
||||
|
||||
void string_compare(Register str1, Register str2,
|
||||
Register cnt1, Register cnt2, Register result,
|
||||
Register tmp1, Register tmp2, FloatRegister vtmp1,
|
||||
FloatRegister vtmp2, FloatRegister vtmp3, int ae);
|
||||
|
||||
void string_indexof(Register str1, Register str2,
|
||||
Register cnt1, Register cnt2,
|
||||
Register tmp1, Register tmp2,
|
||||
Register tmp3, Register tmp4,
|
||||
Register tmp5, Register tmp6,
|
||||
int int_cnt1, Register result, int ae);
|
||||
|
||||
void string_indexof_char(Register str1, Register cnt1,
|
||||
Register ch, Register result,
|
||||
Register tmp1, Register tmp2, Register tmp3);
|
||||
|
||||
#endif // CPU_AARCH64_C2_MACROASSEMBLER_AARCH64_HPP
|
@ -76,14 +76,14 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
||||
|
||||
// So unextended sp must be within the stack but we need not to check
|
||||
// that unextended sp >= sp
|
||||
if (!thread->is_in_full_stack(unextended_sp)) {
|
||||
if (!thread->is_in_full_stack_checked(unextended_sp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// an fp must be within the stack and above (but not equal) sp
|
||||
// second evaluation on fp+ is added to handle situation where fp is -1
|
||||
bool fp_safe = thread->is_in_stack_range_excl(fp, sp) &&
|
||||
thread->is_in_full_stack(fp + (return_addr_offset * sizeof(void*)));
|
||||
thread->is_in_full_stack_checked(fp + (return_addr_offset * sizeof(void*)));
|
||||
|
||||
// We know sp/unextended_sp are safe only fp is questionable here
|
||||
|
||||
@ -145,7 +145,7 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
||||
|
||||
sender_sp = _unextended_sp + _cb->frame_size();
|
||||
// Is sender_sp safe?
|
||||
if (!thread->is_in_full_stack((address)sender_sp)) {
|
||||
if (!thread->is_in_full_stack_checked((address)sender_sp)) {
|
||||
return false;
|
||||
}
|
||||
sender_unextended_sp = sender_sp;
|
||||
@ -264,6 +264,7 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
||||
}
|
||||
|
||||
void frame::patch_pc(Thread* thread, address pc) {
|
||||
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
|
||||
address* pc_addr = &(((address*) sp())[-1]);
|
||||
if (TracePcPatching) {
|
||||
tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]",
|
||||
@ -273,7 +274,6 @@ void frame::patch_pc(Thread* thread, address pc) {
|
||||
// patch in the same address that's already there.
|
||||
assert(_pc == *pc_addr || pc == *pc_addr, "must be");
|
||||
*pc_addr = pc;
|
||||
_cb = CodeCache::find_blob(pc);
|
||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||
if (original_pc != NULL) {
|
||||
assert(original_pc == _pc, "expected original PC to be stored before patching");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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,18 @@ void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm
|
||||
Register addr, Register count, RegSet saved_regs) {
|
||||
bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
|
||||
if (!dest_uninitialized) {
|
||||
Label done;
|
||||
Address in_progress(rthread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()));
|
||||
|
||||
// Is marking active?
|
||||
if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
|
||||
__ ldrw(rscratch1, in_progress);
|
||||
} else {
|
||||
assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
|
||||
__ ldrb(rscratch1, in_progress);
|
||||
}
|
||||
__ cbzw(rscratch1, done);
|
||||
|
||||
__ push(saved_regs, sp);
|
||||
if (count == c_rarg0) {
|
||||
if (addr == c_rarg1) {
|
||||
@ -68,6 +80,8 @@ void G1BarrierSetAssembler::gen_write_ref_array_pre_barrier(MacroAssembler* masm
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_array_pre_oop_entry), 2);
|
||||
}
|
||||
__ pop(saved_regs, sp);
|
||||
|
||||
__ bind(done);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2019, Red Hat, Inc. All rights reserved.
|
||||
* Copyright (c) 2018, 2020, 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
|
||||
@ -49,17 +49,17 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, Dec
|
||||
Register src, Register dst, Register count, RegSet saved_regs) {
|
||||
if (is_oop) {
|
||||
bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
|
||||
if ((ShenandoahSATBBarrier && !dest_uninitialized) || ShenandoahLoadRefBarrier) {
|
||||
if ((ShenandoahSATBBarrier && !dest_uninitialized) || ShenandoahStoreValEnqueueBarrier || ShenandoahLoadRefBarrier) {
|
||||
|
||||
Label done;
|
||||
|
||||
// Avoid calling runtime if count == 0
|
||||
__ cbz(count, done);
|
||||
|
||||
// Is marking active?
|
||||
// Is GC active?
|
||||
Address gc_state(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
|
||||
__ ldrb(rscratch1, gc_state);
|
||||
if (dest_uninitialized) {
|
||||
if (ShenandoahSATBBarrier && dest_uninitialized) {
|
||||
__ tbz(rscratch1, ShenandoahHeap::HAS_FORWARDED_BITPOS, done);
|
||||
} else {
|
||||
__ mov(rscratch2, ShenandoahHeap::HAS_FORWARDED | ShenandoahHeap::MARKING);
|
||||
@ -69,17 +69,9 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, Dec
|
||||
|
||||
__ push(saved_regs, sp);
|
||||
if (UseCompressedOops) {
|
||||
if (dest_uninitialized) {
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_array_pre_duinit_narrow_oop_entry), src, dst, count);
|
||||
} else {
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_array_pre_narrow_oop_entry), src, dst, count);
|
||||
}
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_narrow_oop_entry), src, dst, count);
|
||||
} else {
|
||||
if (dest_uninitialized) {
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_array_pre_duinit_oop_entry), src, dst, count);
|
||||
} else {
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_array_pre_oop_entry), src, dst, count);
|
||||
}
|
||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_oop_entry), src, dst, count);
|
||||
}
|
||||
__ pop(saved_regs, sp);
|
||||
__ bind(done);
|
||||
@ -384,6 +376,7 @@ void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet d
|
||||
// 3: apply keep-alive barrier if needed
|
||||
if (ShenandoahBarrierSet::need_keep_alive_barrier(decorators, type)) {
|
||||
__ enter();
|
||||
__ push_call_clobbered_registers();
|
||||
satb_write_barrier_pre(masm /* masm */,
|
||||
noreg /* obj */,
|
||||
dst /* pre_val */,
|
||||
@ -391,6 +384,7 @@ void ShenandoahBarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet d
|
||||
tmp1 /* tmp */,
|
||||
true /* tosca_live */,
|
||||
true /* expand_call */);
|
||||
__ pop_call_clobbered_registers();
|
||||
__ leave();
|
||||
}
|
||||
}
|
||||
@ -614,7 +608,7 @@ void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAss
|
||||
// Is marking still active?
|
||||
Address gc_state(thread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
|
||||
__ ldrb(tmp, gc_state);
|
||||
__ mov(rscratch2, ShenandoahHeap::MARKING | ShenandoahHeap::TRAVERSAL);
|
||||
__ mov(rscratch2, ShenandoahHeap::MARKING);
|
||||
__ tst(tmp, rscratch2);
|
||||
__ br(Assembler::EQ, done);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2020, 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.
|
||||
*
|
||||
@ -56,8 +56,6 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
|
||||
|
||||
#define SUPPORT_RESERVED_STACK_AREA
|
||||
|
||||
#define THREAD_LOCAL_POLL
|
||||
|
||||
#define PREFERRED_METASPACE_ALIGNMENT
|
||||
|
||||
#endif // CPU_AARCH64_GLOBALDEFINITIONS_AARCH64_HPP
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2020, 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.
|
||||
*
|
||||
@ -469,8 +469,7 @@ void InterpreterMacroAssembler::dispatch_base(TosState state,
|
||||
|
||||
Label safepoint;
|
||||
address* const safepoint_table = Interpreter::safept_table(state);
|
||||
bool needs_thread_local_poll = generate_poll &&
|
||||
SafepointMechanism::uses_thread_local_poll() && table != safepoint_table;
|
||||
bool needs_thread_local_poll = generate_poll && table != safepoint_table;
|
||||
|
||||
if (needs_thread_local_poll) {
|
||||
NOT_PRODUCT(block_comment("Thread-local Safepoint poll"));
|
||||
|
@ -54,7 +54,6 @@
|
||||
#ifdef COMPILER2
|
||||
#include "oops/oop.hpp"
|
||||
#include "opto/compile.hpp"
|
||||
#include "opto/intrinsicnode.hpp"
|
||||
#include "opto/node.hpp"
|
||||
#include "opto/output.hpp"
|
||||
#endif
|
||||
@ -292,16 +291,8 @@ address MacroAssembler::target_addr_for_insn(address insn_addr, unsigned insn) {
|
||||
}
|
||||
|
||||
void MacroAssembler::safepoint_poll(Label& slow_path) {
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
ldr(rscratch1, Address(rthread, Thread::polling_page_offset()));
|
||||
tbnz(rscratch1, exact_log2(SafepointMechanism::poll_bit()), slow_path);
|
||||
} else {
|
||||
unsigned long offset;
|
||||
adrp(rscratch1, ExternalAddress(SafepointSynchronize::address_of_state()), offset);
|
||||
ldrw(rscratch1, Address(rscratch1, offset));
|
||||
assert(SafepointSynchronize::_not_synchronized == 0, "rewrite this code");
|
||||
cbnz(rscratch1, slow_path);
|
||||
}
|
||||
ldr(rscratch1, Address(rthread, Thread::polling_page_offset()));
|
||||
tbnz(rscratch1, exact_log2(SafepointMechanism::poll_bit()), slow_path);
|
||||
}
|
||||
|
||||
// Just like safepoint_poll, but use an acquiring load for thread-
|
||||
@ -317,13 +308,9 @@ void MacroAssembler::safepoint_poll(Label& slow_path) {
|
||||
// racing the code which wakes up from a safepoint.
|
||||
//
|
||||
void MacroAssembler::safepoint_poll_acquire(Label& slow_path) {
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
lea(rscratch1, Address(rthread, Thread::polling_page_offset()));
|
||||
ldar(rscratch1, rscratch1);
|
||||
tbnz(rscratch1, exact_log2(SafepointMechanism::poll_bit()), slow_path);
|
||||
} else {
|
||||
safepoint_poll(slow_path);
|
||||
}
|
||||
lea(rscratch1, Address(rthread, Thread::polling_page_offset()));
|
||||
ldar(rscratch1, rscratch1);
|
||||
tbnz(rscratch1, exact_log2(SafepointMechanism::poll_bit()), slow_path);
|
||||
}
|
||||
|
||||
void MacroAssembler::reset_last_Java_frame(bool clear_fp) {
|
||||
@ -4306,22 +4293,15 @@ void MacroAssembler::bang_stack_size(Register size, Register tmp) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Move the address of the polling page into dest.
|
||||
void MacroAssembler::get_polling_page(Register dest, address page, relocInfo::relocType rtype) {
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
ldr(dest, Address(rthread, Thread::polling_page_offset()));
|
||||
} else {
|
||||
unsigned long off;
|
||||
adrp(dest, Address(page, rtype), off);
|
||||
assert(off == 0, "polling page must be page aligned");
|
||||
}
|
||||
void MacroAssembler::get_polling_page(Register dest, relocInfo::relocType rtype) {
|
||||
ldr(dest, Address(rthread, Thread::polling_page_offset()));
|
||||
}
|
||||
|
||||
// Move the address of the polling page into r, then read the polling
|
||||
// page.
|
||||
address MacroAssembler::read_polling_page(Register r, address page, relocInfo::relocType rtype) {
|
||||
get_polling_page(r, page, rtype);
|
||||
address MacroAssembler::fetch_and_read_polling_page(Register r, relocInfo::relocType rtype) {
|
||||
get_polling_page(r, rtype);
|
||||
return read_polling_page(r, rtype);
|
||||
}
|
||||
|
||||
@ -4414,737 +4394,6 @@ void MacroAssembler::remove_frame(int framesize) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COMPILER2
|
||||
typedef void (MacroAssembler::* chr_insn)(Register Rt, const Address &adr);
|
||||
|
||||
// Search for str1 in str2 and return index or -1
|
||||
void MacroAssembler::string_indexof(Register str2, Register str1,
|
||||
Register cnt2, Register cnt1,
|
||||
Register tmp1, Register tmp2,
|
||||
Register tmp3, Register tmp4,
|
||||
Register tmp5, Register tmp6,
|
||||
int icnt1, Register result, int ae) {
|
||||
// NOTE: tmp5, tmp6 can be zr depending on specific method version
|
||||
Label LINEARSEARCH, LINEARSTUB, LINEAR_MEDIUM, DONE, NOMATCH, MATCH;
|
||||
|
||||
Register ch1 = rscratch1;
|
||||
Register ch2 = rscratch2;
|
||||
Register cnt1tmp = tmp1;
|
||||
Register cnt2tmp = tmp2;
|
||||
Register cnt1_neg = cnt1;
|
||||
Register cnt2_neg = cnt2;
|
||||
Register result_tmp = tmp4;
|
||||
|
||||
bool isL = ae == StrIntrinsicNode::LL;
|
||||
|
||||
bool str1_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UL;
|
||||
bool str2_isL = ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::LU;
|
||||
int str1_chr_shift = str1_isL ? 0:1;
|
||||
int str2_chr_shift = str2_isL ? 0:1;
|
||||
int str1_chr_size = str1_isL ? 1:2;
|
||||
int str2_chr_size = str2_isL ? 1:2;
|
||||
chr_insn str1_load_1chr = str1_isL ? (chr_insn)&MacroAssembler::ldrb :
|
||||
(chr_insn)&MacroAssembler::ldrh;
|
||||
chr_insn str2_load_1chr = str2_isL ? (chr_insn)&MacroAssembler::ldrb :
|
||||
(chr_insn)&MacroAssembler::ldrh;
|
||||
chr_insn load_2chr = isL ? (chr_insn)&MacroAssembler::ldrh : (chr_insn)&MacroAssembler::ldrw;
|
||||
chr_insn load_4chr = isL ? (chr_insn)&MacroAssembler::ldrw : (chr_insn)&MacroAssembler::ldr;
|
||||
|
||||
// Note, inline_string_indexOf() generates checks:
|
||||
// if (substr.count > string.count) return -1;
|
||||
// if (substr.count == 0) return 0;
|
||||
|
||||
// We have two strings, a source string in str2, cnt2 and a pattern string
|
||||
// in str1, cnt1. Find the 1st occurence of pattern in source or return -1.
|
||||
|
||||
// For larger pattern and source we use a simplified Boyer Moore algorithm.
|
||||
// With a small pattern and source we use linear scan.
|
||||
|
||||
if (icnt1 == -1) {
|
||||
sub(result_tmp, cnt2, cnt1);
|
||||
cmp(cnt1, (u1)8); // Use Linear Scan if cnt1 < 8 || cnt1 >= 256
|
||||
br(LT, LINEARSEARCH);
|
||||
dup(v0, T16B, cnt1); // done in separate FPU pipeline. Almost no penalty
|
||||
subs(zr, cnt1, 256);
|
||||
lsr(tmp1, cnt2, 2);
|
||||
ccmp(cnt1, tmp1, 0b0000, LT); // Source must be 4 * pattern for BM
|
||||
br(GE, LINEARSTUB);
|
||||
}
|
||||
|
||||
// The Boyer Moore alogorithm is based on the description here:-
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm
|
||||
//
|
||||
// This describes and algorithm with 2 shift rules. The 'Bad Character' rule
|
||||
// and the 'Good Suffix' rule.
|
||||
//
|
||||
// These rules are essentially heuristics for how far we can shift the
|
||||
// pattern along the search string.
|
||||
//
|
||||
// The implementation here uses the 'Bad Character' rule only because of the
|
||||
// complexity of initialisation for the 'Good Suffix' rule.
|
||||
//
|
||||
// This is also known as the Boyer-Moore-Horspool algorithm:-
|
||||
//
|
||||
// http://en.wikipedia.org/wiki/Boyer-Moore-Horspool_algorithm
|
||||
//
|
||||
// This particular implementation has few java-specific optimizations.
|
||||
//
|
||||
// #define ASIZE 256
|
||||
//
|
||||
// int bm(unsigned char *x, int m, unsigned char *y, int n) {
|
||||
// int i, j;
|
||||
// unsigned c;
|
||||
// unsigned char bc[ASIZE];
|
||||
//
|
||||
// /* Preprocessing */
|
||||
// for (i = 0; i < ASIZE; ++i)
|
||||
// bc[i] = m;
|
||||
// for (i = 0; i < m - 1; ) {
|
||||
// c = x[i];
|
||||
// ++i;
|
||||
// // c < 256 for Latin1 string, so, no need for branch
|
||||
// #ifdef PATTERN_STRING_IS_LATIN1
|
||||
// bc[c] = m - i;
|
||||
// #else
|
||||
// if (c < ASIZE) bc[c] = m - i;
|
||||
// #endif
|
||||
// }
|
||||
//
|
||||
// /* Searching */
|
||||
// j = 0;
|
||||
// while (j <= n - m) {
|
||||
// c = y[i+j];
|
||||
// if (x[m-1] == c)
|
||||
// for (i = m - 2; i >= 0 && x[i] == y[i + j]; --i);
|
||||
// if (i < 0) return j;
|
||||
// // c < 256 for Latin1 string, so, no need for branch
|
||||
// #ifdef SOURCE_STRING_IS_LATIN1
|
||||
// // LL case: (c< 256) always true. Remove branch
|
||||
// j += bc[y[j+m-1]];
|
||||
// #endif
|
||||
// #ifndef PATTERN_STRING_IS_UTF
|
||||
// // UU case: need if (c<ASIZE) check. Skip 1 character if not.
|
||||
// if (c < ASIZE)
|
||||
// j += bc[y[j+m-1]];
|
||||
// else
|
||||
// j += 1
|
||||
// #endif
|
||||
// #ifdef PATTERN_IS_LATIN1_AND_SOURCE_IS_UTF
|
||||
// // UL case: need if (c<ASIZE) check. Skip <pattern length> if not.
|
||||
// if (c < ASIZE)
|
||||
// j += bc[y[j+m-1]];
|
||||
// else
|
||||
// j += m
|
||||
// #endif
|
||||
// }
|
||||
// }
|
||||
|
||||
if (icnt1 == -1) {
|
||||
Label BCLOOP, BCSKIP, BMLOOPSTR2, BMLOOPSTR1, BMSKIP, BMADV, BMMATCH,
|
||||
BMLOOPSTR1_LASTCMP, BMLOOPSTR1_CMP, BMLOOPSTR1_AFTER_LOAD, BM_INIT_LOOP;
|
||||
Register cnt1end = tmp2;
|
||||
Register str2end = cnt2;
|
||||
Register skipch = tmp2;
|
||||
|
||||
// str1 length is >=8, so, we can read at least 1 register for cases when
|
||||
// UTF->Latin1 conversion is not needed(8 LL or 4UU) and half register for
|
||||
// UL case. We'll re-read last character in inner pre-loop code to have
|
||||
// single outer pre-loop load
|
||||
const int firstStep = isL ? 7 : 3;
|
||||
|
||||
const int ASIZE = 256;
|
||||
const int STORED_BYTES = 32; // amount of bytes stored per instruction
|
||||
sub(sp, sp, ASIZE);
|
||||
mov(tmp5, ASIZE/STORED_BYTES); // loop iterations
|
||||
mov(ch1, sp);
|
||||
BIND(BM_INIT_LOOP);
|
||||
stpq(v0, v0, Address(post(ch1, STORED_BYTES)));
|
||||
subs(tmp5, tmp5, 1);
|
||||
br(GT, BM_INIT_LOOP);
|
||||
|
||||
sub(cnt1tmp, cnt1, 1);
|
||||
mov(tmp5, str2);
|
||||
add(str2end, str2, result_tmp, LSL, str2_chr_shift);
|
||||
sub(ch2, cnt1, 1);
|
||||
mov(tmp3, str1);
|
||||
BIND(BCLOOP);
|
||||
(this->*str1_load_1chr)(ch1, Address(post(tmp3, str1_chr_size)));
|
||||
if (!str1_isL) {
|
||||
subs(zr, ch1, ASIZE);
|
||||
br(HS, BCSKIP);
|
||||
}
|
||||
strb(ch2, Address(sp, ch1));
|
||||
BIND(BCSKIP);
|
||||
subs(ch2, ch2, 1);
|
||||
br(GT, BCLOOP);
|
||||
|
||||
add(tmp6, str1, cnt1, LSL, str1_chr_shift); // address after str1
|
||||
if (str1_isL == str2_isL) {
|
||||
// load last 8 bytes (8LL/4UU symbols)
|
||||
ldr(tmp6, Address(tmp6, -wordSize));
|
||||
} else {
|
||||
ldrw(tmp6, Address(tmp6, -wordSize/2)); // load last 4 bytes(4 symbols)
|
||||
// convert Latin1 to UTF. We'll have to wait until load completed, but
|
||||
// it's still faster than per-character loads+checks
|
||||
lsr(tmp3, tmp6, BitsPerByte * (wordSize/2 - str1_chr_size)); // str1[N-1]
|
||||
ubfx(ch1, tmp6, 8, 8); // str1[N-2]
|
||||
ubfx(ch2, tmp6, 16, 8); // str1[N-3]
|
||||
andr(tmp6, tmp6, 0xFF); // str1[N-4]
|
||||
orr(ch2, ch1, ch2, LSL, 16);
|
||||
orr(tmp6, tmp6, tmp3, LSL, 48);
|
||||
orr(tmp6, tmp6, ch2, LSL, 16);
|
||||
}
|
||||
BIND(BMLOOPSTR2);
|
||||
(this->*str2_load_1chr)(skipch, Address(str2, cnt1tmp, Address::lsl(str2_chr_shift)));
|
||||
sub(cnt1tmp, cnt1tmp, firstStep); // cnt1tmp is positive here, because cnt1 >= 8
|
||||
if (str1_isL == str2_isL) {
|
||||
// re-init tmp3. It's for free because it's executed in parallel with
|
||||
// load above. Alternative is to initialize it before loop, but it'll
|
||||
// affect performance on in-order systems with 2 or more ld/st pipelines
|
||||
lsr(tmp3, tmp6, BitsPerByte * (wordSize - str1_chr_size));
|
||||
}
|
||||
if (!isL) { // UU/UL case
|
||||
lsl(ch2, cnt1tmp, 1); // offset in bytes
|
||||
}
|
||||
cmp(tmp3, skipch);
|
||||
br(NE, BMSKIP);
|
||||
ldr(ch2, Address(str2, isL ? cnt1tmp : ch2));
|
||||
mov(ch1, tmp6);
|
||||
if (isL) {
|
||||
b(BMLOOPSTR1_AFTER_LOAD);
|
||||
} else {
|
||||
sub(cnt1tmp, cnt1tmp, 1); // no need to branch for UU/UL case. cnt1 >= 8
|
||||
b(BMLOOPSTR1_CMP);
|
||||
}
|
||||
BIND(BMLOOPSTR1);
|
||||
(this->*str1_load_1chr)(ch1, Address(str1, cnt1tmp, Address::lsl(str1_chr_shift)));
|
||||
(this->*str2_load_1chr)(ch2, Address(str2, cnt1tmp, Address::lsl(str2_chr_shift)));
|
||||
BIND(BMLOOPSTR1_AFTER_LOAD);
|
||||
subs(cnt1tmp, cnt1tmp, 1);
|
||||
br(LT, BMLOOPSTR1_LASTCMP);
|
||||
BIND(BMLOOPSTR1_CMP);
|
||||
cmp(ch1, ch2);
|
||||
br(EQ, BMLOOPSTR1);
|
||||
BIND(BMSKIP);
|
||||
if (!isL) {
|
||||
// if we've met UTF symbol while searching Latin1 pattern, then we can
|
||||
// skip cnt1 symbols
|
||||
if (str1_isL != str2_isL) {
|
||||
mov(result_tmp, cnt1);
|
||||
} else {
|
||||
mov(result_tmp, 1);
|
||||
}
|
||||
subs(zr, skipch, ASIZE);
|
||||
br(HS, BMADV);
|
||||
}
|
||||
ldrb(result_tmp, Address(sp, skipch)); // load skip distance
|
||||
BIND(BMADV);
|
||||
sub(cnt1tmp, cnt1, 1);
|
||||
add(str2, str2, result_tmp, LSL, str2_chr_shift);
|
||||
cmp(str2, str2end);
|
||||
br(LE, BMLOOPSTR2);
|
||||
add(sp, sp, ASIZE);
|
||||
b(NOMATCH);
|
||||
BIND(BMLOOPSTR1_LASTCMP);
|
||||
cmp(ch1, ch2);
|
||||
br(NE, BMSKIP);
|
||||
BIND(BMMATCH);
|
||||
sub(result, str2, tmp5);
|
||||
if (!str2_isL) lsr(result, result, 1);
|
||||
add(sp, sp, ASIZE);
|
||||
b(DONE);
|
||||
|
||||
BIND(LINEARSTUB);
|
||||
cmp(cnt1, (u1)16); // small patterns still should be handled by simple algorithm
|
||||
br(LT, LINEAR_MEDIUM);
|
||||
mov(result, zr);
|
||||
RuntimeAddress stub = NULL;
|
||||
if (isL) {
|
||||
stub = RuntimeAddress(StubRoutines::aarch64::string_indexof_linear_ll());
|
||||
assert(stub.target() != NULL, "string_indexof_linear_ll stub has not been generated");
|
||||
} else if (str1_isL) {
|
||||
stub = RuntimeAddress(StubRoutines::aarch64::string_indexof_linear_ul());
|
||||
assert(stub.target() != NULL, "string_indexof_linear_ul stub has not been generated");
|
||||
} else {
|
||||
stub = RuntimeAddress(StubRoutines::aarch64::string_indexof_linear_uu());
|
||||
assert(stub.target() != NULL, "string_indexof_linear_uu stub has not been generated");
|
||||
}
|
||||
trampoline_call(stub);
|
||||
b(DONE);
|
||||
}
|
||||
|
||||
BIND(LINEARSEARCH);
|
||||
{
|
||||
Label DO1, DO2, DO3;
|
||||
|
||||
Register str2tmp = tmp2;
|
||||
Register first = tmp3;
|
||||
|
||||
if (icnt1 == -1)
|
||||
{
|
||||
Label DOSHORT, FIRST_LOOP, STR2_NEXT, STR1_LOOP, STR1_NEXT;
|
||||
|
||||
cmp(cnt1, u1(str1_isL == str2_isL ? 4 : 2));
|
||||
br(LT, DOSHORT);
|
||||
BIND(LINEAR_MEDIUM);
|
||||
(this->*str1_load_1chr)(first, Address(str1));
|
||||
lea(str1, Address(str1, cnt1, Address::lsl(str1_chr_shift)));
|
||||
sub(cnt1_neg, zr, cnt1, LSL, str1_chr_shift);
|
||||
lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
|
||||
sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
|
||||
|
||||
BIND(FIRST_LOOP);
|
||||
(this->*str2_load_1chr)(ch2, Address(str2, cnt2_neg));
|
||||
cmp(first, ch2);
|
||||
br(EQ, STR1_LOOP);
|
||||
BIND(STR2_NEXT);
|
||||
adds(cnt2_neg, cnt2_neg, str2_chr_size);
|
||||
br(LE, FIRST_LOOP);
|
||||
b(NOMATCH);
|
||||
|
||||
BIND(STR1_LOOP);
|
||||
adds(cnt1tmp, cnt1_neg, str1_chr_size);
|
||||
add(cnt2tmp, cnt2_neg, str2_chr_size);
|
||||
br(GE, MATCH);
|
||||
|
||||
BIND(STR1_NEXT);
|
||||
(this->*str1_load_1chr)(ch1, Address(str1, cnt1tmp));
|
||||
(this->*str2_load_1chr)(ch2, Address(str2, cnt2tmp));
|
||||
cmp(ch1, ch2);
|
||||
br(NE, STR2_NEXT);
|
||||
adds(cnt1tmp, cnt1tmp, str1_chr_size);
|
||||
add(cnt2tmp, cnt2tmp, str2_chr_size);
|
||||
br(LT, STR1_NEXT);
|
||||
b(MATCH);
|
||||
|
||||
BIND(DOSHORT);
|
||||
if (str1_isL == str2_isL) {
|
||||
cmp(cnt1, (u1)2);
|
||||
br(LT, DO1);
|
||||
br(GT, DO3);
|
||||
}
|
||||
}
|
||||
|
||||
if (icnt1 == 4) {
|
||||
Label CH1_LOOP;
|
||||
|
||||
(this->*load_4chr)(ch1, str1);
|
||||
sub(result_tmp, cnt2, 4);
|
||||
lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
|
||||
sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
|
||||
|
||||
BIND(CH1_LOOP);
|
||||
(this->*load_4chr)(ch2, Address(str2, cnt2_neg));
|
||||
cmp(ch1, ch2);
|
||||
br(EQ, MATCH);
|
||||
adds(cnt2_neg, cnt2_neg, str2_chr_size);
|
||||
br(LE, CH1_LOOP);
|
||||
b(NOMATCH);
|
||||
}
|
||||
|
||||
if ((icnt1 == -1 && str1_isL == str2_isL) || icnt1 == 2) {
|
||||
Label CH1_LOOP;
|
||||
|
||||
BIND(DO2);
|
||||
(this->*load_2chr)(ch1, str1);
|
||||
if (icnt1 == 2) {
|
||||
sub(result_tmp, cnt2, 2);
|
||||
}
|
||||
lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
|
||||
sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
|
||||
BIND(CH1_LOOP);
|
||||
(this->*load_2chr)(ch2, Address(str2, cnt2_neg));
|
||||
cmp(ch1, ch2);
|
||||
br(EQ, MATCH);
|
||||
adds(cnt2_neg, cnt2_neg, str2_chr_size);
|
||||
br(LE, CH1_LOOP);
|
||||
b(NOMATCH);
|
||||
}
|
||||
|
||||
if ((icnt1 == -1 && str1_isL == str2_isL) || icnt1 == 3) {
|
||||
Label FIRST_LOOP, STR2_NEXT, STR1_LOOP;
|
||||
|
||||
BIND(DO3);
|
||||
(this->*load_2chr)(first, str1);
|
||||
(this->*str1_load_1chr)(ch1, Address(str1, 2*str1_chr_size));
|
||||
if (icnt1 == 3) {
|
||||
sub(result_tmp, cnt2, 3);
|
||||
}
|
||||
lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
|
||||
sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
|
||||
BIND(FIRST_LOOP);
|
||||
(this->*load_2chr)(ch2, Address(str2, cnt2_neg));
|
||||
cmpw(first, ch2);
|
||||
br(EQ, STR1_LOOP);
|
||||
BIND(STR2_NEXT);
|
||||
adds(cnt2_neg, cnt2_neg, str2_chr_size);
|
||||
br(LE, FIRST_LOOP);
|
||||
b(NOMATCH);
|
||||
|
||||
BIND(STR1_LOOP);
|
||||
add(cnt2tmp, cnt2_neg, 2*str2_chr_size);
|
||||
(this->*str2_load_1chr)(ch2, Address(str2, cnt2tmp));
|
||||
cmp(ch1, ch2);
|
||||
br(NE, STR2_NEXT);
|
||||
b(MATCH);
|
||||
}
|
||||
|
||||
if (icnt1 == -1 || icnt1 == 1) {
|
||||
Label CH1_LOOP, HAS_ZERO, DO1_SHORT, DO1_LOOP;
|
||||
|
||||
BIND(DO1);
|
||||
(this->*str1_load_1chr)(ch1, str1);
|
||||
cmp(cnt2, (u1)8);
|
||||
br(LT, DO1_SHORT);
|
||||
|
||||
sub(result_tmp, cnt2, 8/str2_chr_size);
|
||||
sub(cnt2_neg, zr, result_tmp, LSL, str2_chr_shift);
|
||||
mov(tmp3, str2_isL ? 0x0101010101010101 : 0x0001000100010001);
|
||||
lea(str2, Address(str2, result_tmp, Address::lsl(str2_chr_shift)));
|
||||
|
||||
if (str2_isL) {
|
||||
orr(ch1, ch1, ch1, LSL, 8);
|
||||
}
|
||||
orr(ch1, ch1, ch1, LSL, 16);
|
||||
orr(ch1, ch1, ch1, LSL, 32);
|
||||
BIND(CH1_LOOP);
|
||||
ldr(ch2, Address(str2, cnt2_neg));
|
||||
eor(ch2, ch1, ch2);
|
||||
sub(tmp1, ch2, tmp3);
|
||||
orr(tmp2, ch2, str2_isL ? 0x7f7f7f7f7f7f7f7f : 0x7fff7fff7fff7fff);
|
||||
bics(tmp1, tmp1, tmp2);
|
||||
br(NE, HAS_ZERO);
|
||||
adds(cnt2_neg, cnt2_neg, 8);
|
||||
br(LT, CH1_LOOP);
|
||||
|
||||
cmp(cnt2_neg, (u1)8);
|
||||
mov(cnt2_neg, 0);
|
||||
br(LT, CH1_LOOP);
|
||||
b(NOMATCH);
|
||||
|
||||
BIND(HAS_ZERO);
|
||||
rev(tmp1, tmp1);
|
||||
clz(tmp1, tmp1);
|
||||
add(cnt2_neg, cnt2_neg, tmp1, LSR, 3);
|
||||
b(MATCH);
|
||||
|
||||
BIND(DO1_SHORT);
|
||||
mov(result_tmp, cnt2);
|
||||
lea(str2, Address(str2, cnt2, Address::lsl(str2_chr_shift)));
|
||||
sub(cnt2_neg, zr, cnt2, LSL, str2_chr_shift);
|
||||
BIND(DO1_LOOP);
|
||||
(this->*str2_load_1chr)(ch2, Address(str2, cnt2_neg));
|
||||
cmpw(ch1, ch2);
|
||||
br(EQ, MATCH);
|
||||
adds(cnt2_neg, cnt2_neg, str2_chr_size);
|
||||
br(LT, DO1_LOOP);
|
||||
}
|
||||
}
|
||||
BIND(NOMATCH);
|
||||
mov(result, -1);
|
||||
b(DONE);
|
||||
BIND(MATCH);
|
||||
add(result, result_tmp, cnt2_neg, ASR, str2_chr_shift);
|
||||
BIND(DONE);
|
||||
}
|
||||
|
||||
typedef void (MacroAssembler::* chr_insn)(Register Rt, const Address &adr);
|
||||
typedef void (MacroAssembler::* uxt_insn)(Register Rd, Register Rn);
|
||||
|
||||
void MacroAssembler::string_indexof_char(Register str1, Register cnt1,
|
||||
Register ch, Register result,
|
||||
Register tmp1, Register tmp2, Register tmp3)
|
||||
{
|
||||
Label CH1_LOOP, HAS_ZERO, DO1_SHORT, DO1_LOOP, MATCH, NOMATCH, DONE;
|
||||
Register cnt1_neg = cnt1;
|
||||
Register ch1 = rscratch1;
|
||||
Register result_tmp = rscratch2;
|
||||
|
||||
cbz(cnt1, NOMATCH);
|
||||
|
||||
cmp(cnt1, (u1)4);
|
||||
br(LT, DO1_SHORT);
|
||||
|
||||
orr(ch, ch, ch, LSL, 16);
|
||||
orr(ch, ch, ch, LSL, 32);
|
||||
|
||||
sub(cnt1, cnt1, 4);
|
||||
mov(result_tmp, cnt1);
|
||||
lea(str1, Address(str1, cnt1, Address::uxtw(1)));
|
||||
sub(cnt1_neg, zr, cnt1, LSL, 1);
|
||||
|
||||
mov(tmp3, 0x0001000100010001);
|
||||
|
||||
BIND(CH1_LOOP);
|
||||
ldr(ch1, Address(str1, cnt1_neg));
|
||||
eor(ch1, ch, ch1);
|
||||
sub(tmp1, ch1, tmp3);
|
||||
orr(tmp2, ch1, 0x7fff7fff7fff7fff);
|
||||
bics(tmp1, tmp1, tmp2);
|
||||
br(NE, HAS_ZERO);
|
||||
adds(cnt1_neg, cnt1_neg, 8);
|
||||
br(LT, CH1_LOOP);
|
||||
|
||||
cmp(cnt1_neg, (u1)8);
|
||||
mov(cnt1_neg, 0);
|
||||
br(LT, CH1_LOOP);
|
||||
b(NOMATCH);
|
||||
|
||||
BIND(HAS_ZERO);
|
||||
rev(tmp1, tmp1);
|
||||
clz(tmp1, tmp1);
|
||||
add(cnt1_neg, cnt1_neg, tmp1, LSR, 3);
|
||||
b(MATCH);
|
||||
|
||||
BIND(DO1_SHORT);
|
||||
mov(result_tmp, cnt1);
|
||||
lea(str1, Address(str1, cnt1, Address::uxtw(1)));
|
||||
sub(cnt1_neg, zr, cnt1, LSL, 1);
|
||||
BIND(DO1_LOOP);
|
||||
ldrh(ch1, Address(str1, cnt1_neg));
|
||||
cmpw(ch, ch1);
|
||||
br(EQ, MATCH);
|
||||
adds(cnt1_neg, cnt1_neg, 2);
|
||||
br(LT, DO1_LOOP);
|
||||
BIND(NOMATCH);
|
||||
mov(result, -1);
|
||||
b(DONE);
|
||||
BIND(MATCH);
|
||||
add(result, result_tmp, cnt1_neg, ASR, 1);
|
||||
BIND(DONE);
|
||||
}
|
||||
|
||||
// Compare strings.
|
||||
void MacroAssembler::string_compare(Register str1, Register str2,
|
||||
Register cnt1, Register cnt2, Register result, Register tmp1, Register tmp2,
|
||||
FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3, int ae) {
|
||||
Label DONE, SHORT_LOOP, SHORT_STRING, SHORT_LAST, TAIL, STUB,
|
||||
DIFFERENCE, NEXT_WORD, SHORT_LOOP_TAIL, SHORT_LAST2, SHORT_LAST_INIT,
|
||||
SHORT_LOOP_START, TAIL_CHECK;
|
||||
|
||||
bool isLL = ae == StrIntrinsicNode::LL;
|
||||
bool isLU = ae == StrIntrinsicNode::LU;
|
||||
bool isUL = ae == StrIntrinsicNode::UL;
|
||||
|
||||
// The stub threshold for LL strings is: 72 (64 + 8) chars
|
||||
// UU: 36 chars, or 72 bytes (valid for the 64-byte large loop with prefetch)
|
||||
// LU/UL: 24 chars, or 48 bytes (valid for the 16-character loop at least)
|
||||
const u1 stub_threshold = isLL ? 72 : ((isLU || isUL) ? 24 : 36);
|
||||
|
||||
bool str1_isL = isLL || isLU;
|
||||
bool str2_isL = isLL || isUL;
|
||||
|
||||
int str1_chr_shift = str1_isL ? 0 : 1;
|
||||
int str2_chr_shift = str2_isL ? 0 : 1;
|
||||
int str1_chr_size = str1_isL ? 1 : 2;
|
||||
int str2_chr_size = str2_isL ? 1 : 2;
|
||||
int minCharsInWord = isLL ? wordSize : wordSize/2;
|
||||
|
||||
FloatRegister vtmpZ = vtmp1, vtmp = vtmp2;
|
||||
chr_insn str1_load_chr = str1_isL ? (chr_insn)&MacroAssembler::ldrb :
|
||||
(chr_insn)&MacroAssembler::ldrh;
|
||||
chr_insn str2_load_chr = str2_isL ? (chr_insn)&MacroAssembler::ldrb :
|
||||
(chr_insn)&MacroAssembler::ldrh;
|
||||
uxt_insn ext_chr = isLL ? (uxt_insn)&MacroAssembler::uxtbw :
|
||||
(uxt_insn)&MacroAssembler::uxthw;
|
||||
|
||||
BLOCK_COMMENT("string_compare {");
|
||||
|
||||
// Bizzarely, the counts are passed in bytes, regardless of whether they
|
||||
// are L or U strings, however the result is always in characters.
|
||||
if (!str1_isL) asrw(cnt1, cnt1, 1);
|
||||
if (!str2_isL) asrw(cnt2, cnt2, 1);
|
||||
|
||||
// Compute the minimum of the string lengths and save the difference.
|
||||
subsw(result, cnt1, cnt2);
|
||||
cselw(cnt2, cnt1, cnt2, Assembler::LE); // min
|
||||
|
||||
// A very short string
|
||||
cmpw(cnt2, minCharsInWord);
|
||||
br(Assembler::LE, SHORT_STRING);
|
||||
|
||||
// Compare longwords
|
||||
// load first parts of strings and finish initialization while loading
|
||||
{
|
||||
if (str1_isL == str2_isL) { // LL or UU
|
||||
ldr(tmp1, Address(str1));
|
||||
cmp(str1, str2);
|
||||
br(Assembler::EQ, DONE);
|
||||
ldr(tmp2, Address(str2));
|
||||
cmp(cnt2, stub_threshold);
|
||||
br(GE, STUB);
|
||||
subsw(cnt2, cnt2, minCharsInWord);
|
||||
br(EQ, TAIL_CHECK);
|
||||
lea(str2, Address(str2, cnt2, Address::uxtw(str2_chr_shift)));
|
||||
lea(str1, Address(str1, cnt2, Address::uxtw(str1_chr_shift)));
|
||||
sub(cnt2, zr, cnt2, LSL, str2_chr_shift);
|
||||
} else if (isLU) {
|
||||
ldrs(vtmp, Address(str1));
|
||||
ldr(tmp2, Address(str2));
|
||||
cmp(cnt2, stub_threshold);
|
||||
br(GE, STUB);
|
||||
subw(cnt2, cnt2, 4);
|
||||
eor(vtmpZ, T16B, vtmpZ, vtmpZ);
|
||||
lea(str1, Address(str1, cnt2, Address::uxtw(str1_chr_shift)));
|
||||
lea(str2, Address(str2, cnt2, Address::uxtw(str2_chr_shift)));
|
||||
zip1(vtmp, T8B, vtmp, vtmpZ);
|
||||
sub(cnt1, zr, cnt2, LSL, str1_chr_shift);
|
||||
sub(cnt2, zr, cnt2, LSL, str2_chr_shift);
|
||||
add(cnt1, cnt1, 4);
|
||||
fmovd(tmp1, vtmp);
|
||||
} else { // UL case
|
||||
ldr(tmp1, Address(str1));
|
||||
ldrs(vtmp, Address(str2));
|
||||
cmp(cnt2, stub_threshold);
|
||||
br(GE, STUB);
|
||||
subw(cnt2, cnt2, 4);
|
||||
lea(str1, Address(str1, cnt2, Address::uxtw(str1_chr_shift)));
|
||||
eor(vtmpZ, T16B, vtmpZ, vtmpZ);
|
||||
lea(str2, Address(str2, cnt2, Address::uxtw(str2_chr_shift)));
|
||||
sub(cnt1, zr, cnt2, LSL, str1_chr_shift);
|
||||
zip1(vtmp, T8B, vtmp, vtmpZ);
|
||||
sub(cnt2, zr, cnt2, LSL, str2_chr_shift);
|
||||
add(cnt1, cnt1, 8);
|
||||
fmovd(tmp2, vtmp);
|
||||
}
|
||||
adds(cnt2, cnt2, isUL ? 4 : 8);
|
||||
br(GE, TAIL);
|
||||
eor(rscratch2, tmp1, tmp2);
|
||||
cbnz(rscratch2, DIFFERENCE);
|
||||
// main loop
|
||||
bind(NEXT_WORD);
|
||||
if (str1_isL == str2_isL) {
|
||||
ldr(tmp1, Address(str1, cnt2));
|
||||
ldr(tmp2, Address(str2, cnt2));
|
||||
adds(cnt2, cnt2, 8);
|
||||
} else if (isLU) {
|
||||
ldrs(vtmp, Address(str1, cnt1));
|
||||
ldr(tmp2, Address(str2, cnt2));
|
||||
add(cnt1, cnt1, 4);
|
||||
zip1(vtmp, T8B, vtmp, vtmpZ);
|
||||
fmovd(tmp1, vtmp);
|
||||
adds(cnt2, cnt2, 8);
|
||||
} else { // UL
|
||||
ldrs(vtmp, Address(str2, cnt2));
|
||||
ldr(tmp1, Address(str1, cnt1));
|
||||
zip1(vtmp, T8B, vtmp, vtmpZ);
|
||||
add(cnt1, cnt1, 8);
|
||||
fmovd(tmp2, vtmp);
|
||||
adds(cnt2, cnt2, 4);
|
||||
}
|
||||
br(GE, TAIL);
|
||||
|
||||
eor(rscratch2, tmp1, tmp2);
|
||||
cbz(rscratch2, NEXT_WORD);
|
||||
b(DIFFERENCE);
|
||||
bind(TAIL);
|
||||
eor(rscratch2, tmp1, tmp2);
|
||||
cbnz(rscratch2, DIFFERENCE);
|
||||
// Last longword. In the case where length == 4 we compare the
|
||||
// same longword twice, but that's still faster than another
|
||||
// conditional branch.
|
||||
if (str1_isL == str2_isL) {
|
||||
ldr(tmp1, Address(str1));
|
||||
ldr(tmp2, Address(str2));
|
||||
} else if (isLU) {
|
||||
ldrs(vtmp, Address(str1));
|
||||
ldr(tmp2, Address(str2));
|
||||
zip1(vtmp, T8B, vtmp, vtmpZ);
|
||||
fmovd(tmp1, vtmp);
|
||||
} else { // UL
|
||||
ldrs(vtmp, Address(str2));
|
||||
ldr(tmp1, Address(str1));
|
||||
zip1(vtmp, T8B, vtmp, vtmpZ);
|
||||
fmovd(tmp2, vtmp);
|
||||
}
|
||||
bind(TAIL_CHECK);
|
||||
eor(rscratch2, tmp1, tmp2);
|
||||
cbz(rscratch2, DONE);
|
||||
|
||||
// Find the first different characters in the longwords and
|
||||
// compute their difference.
|
||||
bind(DIFFERENCE);
|
||||
rev(rscratch2, rscratch2);
|
||||
clz(rscratch2, rscratch2);
|
||||
andr(rscratch2, rscratch2, isLL ? -8 : -16);
|
||||
lsrv(tmp1, tmp1, rscratch2);
|
||||
(this->*ext_chr)(tmp1, tmp1);
|
||||
lsrv(tmp2, tmp2, rscratch2);
|
||||
(this->*ext_chr)(tmp2, tmp2);
|
||||
subw(result, tmp1, tmp2);
|
||||
b(DONE);
|
||||
}
|
||||
|
||||
bind(STUB);
|
||||
RuntimeAddress stub = NULL;
|
||||
switch(ae) {
|
||||
case StrIntrinsicNode::LL:
|
||||
stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_LL());
|
||||
break;
|
||||
case StrIntrinsicNode::UU:
|
||||
stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_UU());
|
||||
break;
|
||||
case StrIntrinsicNode::LU:
|
||||
stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_LU());
|
||||
break;
|
||||
case StrIntrinsicNode::UL:
|
||||
stub = RuntimeAddress(StubRoutines::aarch64::compare_long_string_UL());
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
assert(stub.target() != NULL, "compare_long_string stub has not been generated");
|
||||
trampoline_call(stub);
|
||||
b(DONE);
|
||||
|
||||
bind(SHORT_STRING);
|
||||
// Is the minimum length zero?
|
||||
cbz(cnt2, DONE);
|
||||
// arrange code to do most branches while loading and loading next characters
|
||||
// while comparing previous
|
||||
(this->*str1_load_chr)(tmp1, Address(post(str1, str1_chr_size)));
|
||||
subs(cnt2, cnt2, 1);
|
||||
br(EQ, SHORT_LAST_INIT);
|
||||
(this->*str2_load_chr)(cnt1, Address(post(str2, str2_chr_size)));
|
||||
b(SHORT_LOOP_START);
|
||||
bind(SHORT_LOOP);
|
||||
subs(cnt2, cnt2, 1);
|
||||
br(EQ, SHORT_LAST);
|
||||
bind(SHORT_LOOP_START);
|
||||
(this->*str1_load_chr)(tmp2, Address(post(str1, str1_chr_size)));
|
||||
(this->*str2_load_chr)(rscratch1, Address(post(str2, str2_chr_size)));
|
||||
cmp(tmp1, cnt1);
|
||||
br(NE, SHORT_LOOP_TAIL);
|
||||
subs(cnt2, cnt2, 1);
|
||||
br(EQ, SHORT_LAST2);
|
||||
(this->*str1_load_chr)(tmp1, Address(post(str1, str1_chr_size)));
|
||||
(this->*str2_load_chr)(cnt1, Address(post(str2, str2_chr_size)));
|
||||
cmp(tmp2, rscratch1);
|
||||
br(EQ, SHORT_LOOP);
|
||||
sub(result, tmp2, rscratch1);
|
||||
b(DONE);
|
||||
bind(SHORT_LOOP_TAIL);
|
||||
sub(result, tmp1, cnt1);
|
||||
b(DONE);
|
||||
bind(SHORT_LAST2);
|
||||
cmp(tmp2, rscratch1);
|
||||
br(EQ, DONE);
|
||||
sub(result, tmp2, rscratch1);
|
||||
|
||||
b(DONE);
|
||||
bind(SHORT_LAST_INIT);
|
||||
(this->*str2_load_chr)(cnt1, Address(post(str2, str2_chr_size)));
|
||||
bind(SHORT_LAST);
|
||||
cmp(tmp1, cnt1);
|
||||
br(EQ, DONE);
|
||||
sub(result, tmp1, cnt1);
|
||||
|
||||
bind(DONE);
|
||||
|
||||
BLOCK_COMMENT("} string_compare");
|
||||
}
|
||||
#endif // COMPILER2
|
||||
|
||||
// This method checks if provided byte array contains byte with highest bit set.
|
||||
void MacroAssembler::has_negatives(Register ary1, Register len, Register result) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2019, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -1217,9 +1217,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
address read_polling_page(Register r, address page, relocInfo::relocType rtype);
|
||||
address read_polling_page(Register r, relocInfo::relocType rtype);
|
||||
void get_polling_page(Register dest, address page, relocInfo::relocType rtype);
|
||||
void get_polling_page(Register dest, relocInfo::relocType rtype);
|
||||
address fetch_and_read_polling_page(Register r, relocInfo::relocType rtype);
|
||||
|
||||
// CRC32 code for java.util.zip.CRC32::updateBytes() instrinsic.
|
||||
void update_byte_crc32(Register crc, Register val, Register table);
|
||||
@ -1227,11 +1227,6 @@ public:
|
||||
Register table0, Register table1, Register table2, Register table3,
|
||||
bool upper = false);
|
||||
|
||||
void string_compare(Register str1, Register str2,
|
||||
Register cnt1, Register cnt2, Register result,
|
||||
Register tmp1, Register tmp2, FloatRegister vtmp1,
|
||||
FloatRegister vtmp2, FloatRegister vtmp3, int ae);
|
||||
|
||||
void has_negatives(Register ary1, Register len, Register result);
|
||||
|
||||
void arrays_equals(Register a1, Register a2, Register result, Register cnt1,
|
||||
@ -1260,15 +1255,6 @@ public:
|
||||
Register len, Register result,
|
||||
FloatRegister Vtmp1, FloatRegister Vtmp2,
|
||||
FloatRegister Vtmp3, FloatRegister Vtmp4);
|
||||
void string_indexof(Register str1, Register str2,
|
||||
Register cnt1, Register cnt2,
|
||||
Register tmp1, Register tmp2,
|
||||
Register tmp3, Register tmp4,
|
||||
Register tmp5, Register tmp6,
|
||||
int int_cnt1, Register result, int ae);
|
||||
void string_indexof_char(Register str1, Register cnt1,
|
||||
Register ch, Register result,
|
||||
Register tmp1, Register tmp2, Register tmp3);
|
||||
void fast_log(FloatRegister vtmp0, FloatRegister vtmp1, FloatRegister vtmp2,
|
||||
FloatRegister vtmp3, FloatRegister vtmp4, FloatRegister vtmp5,
|
||||
FloatRegister tmpC1, FloatRegister tmpC2, FloatRegister tmpC3,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2019, Red Hat Inc. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, 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
|
||||
@ -44,7 +44,7 @@
|
||||
#ifdef COMPILER1
|
||||
#include "c1/c1_Runtime1.hpp"
|
||||
#endif
|
||||
#if COMPILER2_OR_JVMCI
|
||||
#ifdef COMPILER2
|
||||
#include "adfiles/ad_aarch64.hpp"
|
||||
#include "opto/runtime.hpp"
|
||||
#endif
|
||||
@ -170,11 +170,12 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
|
||||
}
|
||||
|
||||
void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) {
|
||||
#ifndef COMPILER2
|
||||
assert(!restore_vectors, "vectors are generated only by C2 and JVMCI");
|
||||
#endif
|
||||
#if COMPILER2_OR_JVMCI
|
||||
__ pop_CPU_state(restore_vectors);
|
||||
__ leave();
|
||||
#else
|
||||
assert(!restore_vectors, "vectors are generated only by C2 and JVMCI");
|
||||
#endif
|
||||
}
|
||||
|
||||
void RegisterSaver::restore_result_registers(MacroAssembler* masm) {
|
||||
@ -2537,7 +2538,7 @@ uint SharedRuntime::out_preserve_stack_slots() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if COMPILER2_OR_JVMCI
|
||||
#ifdef COMPILER2
|
||||
//------------------------------generate_uncommon_trap_blob--------------------
|
||||
void SharedRuntime::generate_uncommon_trap_blob() {
|
||||
// Allocate space for the code
|
||||
@ -2728,7 +2729,7 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||
_uncommon_trap_blob = UncommonTrapBlob::create(&buffer, oop_maps,
|
||||
SimpleRuntimeFrame::framesize >> 1);
|
||||
}
|
||||
#endif // COMPILER2_OR_JVMCI
|
||||
#endif // COMPILER2
|
||||
|
||||
|
||||
//------------------------------generate_handler_blob------
|
||||
@ -2806,7 +2807,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
|
||||
__ bind(noException);
|
||||
|
||||
Label no_adjust, bail;
|
||||
if (SafepointMechanism::uses_thread_local_poll() && !cause_return) {
|
||||
if (!cause_return) {
|
||||
// If our stashed return pc was modified by the runtime we avoid touching it
|
||||
__ ldr(rscratch1, Address(rfp, wordSize));
|
||||
__ cmp(r20, rscratch1);
|
||||
@ -2936,7 +2937,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha
|
||||
return RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, true);
|
||||
}
|
||||
|
||||
#if COMPILER2_OR_JVMCI
|
||||
#ifdef COMPILER2
|
||||
// This is here instead of runtime_x86_64.cpp because it uses SimpleRuntimeFrame
|
||||
//
|
||||
//------------------------------generate_exception_blob---------------------------
|
||||
@ -3065,4 +3066,4 @@ void OptoRuntime::generate_exception_blob() {
|
||||
// Set exception blob
|
||||
_exception_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1);
|
||||
}
|
||||
#endif // COMPILER2_OR_JVMCI
|
||||
#endif // COMPILER2
|
||||
|
@ -327,11 +327,11 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
} else {
|
||||
if (UseAES) {
|
||||
warning("UseAES specified, but not supported on this CPU");
|
||||
warning("AES instructions are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseAES, false);
|
||||
}
|
||||
if (UseAESIntrinsics) {
|
||||
warning("UseAESIntrinsics specified, but not supported on this CPU");
|
||||
warning("AES intrinsics are not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseAESIntrinsics, false);
|
||||
}
|
||||
}
|
||||
@ -425,6 +425,11 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
|
||||
if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
|
||||
FLAG_SET_DEFAULT(UsePopCountInstruction, true);
|
||||
}
|
||||
|
||||
if (!UsePopCountInstruction) {
|
||||
warning("UsePopCountInstruction is always enabled on this CPU");
|
||||
UsePopCountInstruction = true;
|
||||
}
|
||||
|
||||
|
@ -116,6 +116,13 @@ class HandlerImpl {
|
||||
|
||||
};
|
||||
|
||||
class Node::PD {
|
||||
public:
|
||||
enum NodeFlags {
|
||||
_last_flag = Node::_last_flag
|
||||
};
|
||||
};
|
||||
|
||||
%}
|
||||
|
||||
source %{
|
||||
@ -124,6 +131,16 @@ source %{
|
||||
static FloatRegister reg_to_FloatRegister_object(int register_encoding);
|
||||
static Register reg_to_register_object(int register_encoding);
|
||||
|
||||
void PhaseOutput::pd_perform_mach_node_analysis() {
|
||||
}
|
||||
|
||||
int MachNode::pd_alignment_required() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int MachNode::compute_padding(int current_offset) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ****************************************************************************
|
||||
|
||||
@ -137,7 +154,7 @@ bool SafePointNode::needs_polling_address_input() {
|
||||
|
||||
// emit an interrupt that is caught by the debugger (for debugging compiler)
|
||||
void emit_break(CodeBuffer &cbuf) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ breakpoint();
|
||||
}
|
||||
|
||||
@ -157,7 +174,7 @@ uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
|
||||
|
||||
|
||||
void emit_nop(CodeBuffer &cbuf) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ nop();
|
||||
}
|
||||
|
||||
@ -165,7 +182,7 @@ void emit_nop(CodeBuffer &cbuf) {
|
||||
void emit_call_reloc(CodeBuffer &cbuf, const MachCallNode *n, MachOper *m, RelocationHolder const& rspec) {
|
||||
int ret_addr_offset0 = n->as_MachCall()->ret_addr_offset();
|
||||
int call_site_offset = cbuf.insts()->mark_off();
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ set_inst_mark(); // needed in emit_to_interp_stub() to locate the call
|
||||
address target = (address)m->method();
|
||||
assert(n->as_MachCall()->entry_point() == target, "sanity");
|
||||
@ -212,7 +229,7 @@ void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, Phase
|
||||
void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
|
||||
Compile* C = ra_->C;
|
||||
ConstantTable& constant_table = C->output()->constant_table();
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
Register r = as_Register(ra_->get_encode(this));
|
||||
CodeSection* consts_section = __ code()->consts();
|
||||
@ -269,7 +286,7 @@ void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
|
||||
|
||||
void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
Compile* C = ra_->C;
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
for (int i = 0; i < OptoPrologueNops; i++) {
|
||||
__ nop();
|
||||
@ -339,7 +356,7 @@ void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
|
||||
#endif
|
||||
|
||||
void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Compile* C = ra_->C;
|
||||
|
||||
size_t framesize = C->output()->frame_size_in_bytes();
|
||||
@ -367,13 +384,6 @@ const Pipeline * MachEpilogNode::pipeline() const {
|
||||
return MachNode::pipeline_class();
|
||||
}
|
||||
|
||||
int MachEpilogNode::safepoint_offset() const {
|
||||
assert( do_polling(), "no return for this epilog node");
|
||||
// return MacroAssembler::size_of_sethi(os::get_polling_page());
|
||||
Unimplemented();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// Figure out which register class each belongs in: rc_int, rc_float, rc_stack
|
||||
@ -429,7 +439,7 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf,
|
||||
// Bailout only for real instruction emit.
|
||||
// This requires a single comment change in shared code. ( see output.cpp "Normal" instruction case )
|
||||
|
||||
MacroAssembler _masm(cbuf);
|
||||
C2_MacroAssembler _masm(cbuf);
|
||||
|
||||
// --------------------------------------
|
||||
// Check for mem-mem move. Load into unused float registers and fall into
|
||||
@ -790,7 +800,7 @@ void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const {
|
||||
#endif
|
||||
|
||||
void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
for(int i = 0; i < _count; i += 1) {
|
||||
__ nop();
|
||||
}
|
||||
@ -811,7 +821,7 @@ void BoxLockNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
|
||||
#endif
|
||||
|
||||
void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
|
||||
int reg = ra_->get_encode(this);
|
||||
Register dst = reg_to_register_object(reg);
|
||||
@ -847,7 +857,7 @@ void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
|
||||
#endif
|
||||
|
||||
void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register iCache = reg_to_register_object(Matcher::inline_cache_reg_encode());
|
||||
assert(iCache == Ricklass, "should be");
|
||||
Register receiver = R0;
|
||||
@ -866,7 +876,7 @@ uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
|
||||
|
||||
// Emit exception handler code.
|
||||
int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
address base = __ start_a_stub(size_exception_handler());
|
||||
if (base == NULL) {
|
||||
@ -889,7 +899,7 @@ int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) {
|
||||
int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
|
||||
// Can't use any of the current frame's registers as we may have deopted
|
||||
// at a poll and everything can be live.
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
address base = __ start_a_stub(size_deopt_handler());
|
||||
if (base == NULL) {
|
||||
@ -1092,10 +1102,19 @@ bool Matcher::is_generic_vector(MachOper* opnd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Should the matcher clone input 'm' of node 'n'?
|
||||
bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
|
||||
if (is_vshift_con_pattern(n, m)) { // ShiftV src (ShiftCntV con)
|
||||
mstack.push(m, Visit); // m = ShiftCntV
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Should the Matcher clone shifts on addressing modes, expecting them
|
||||
// to be subsumed into complex addressing expressions or compute them
|
||||
// into registers?
|
||||
bool Matcher::clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
|
||||
bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
|
||||
return clone_base_plus_offset_address(m, mstack, address_visited);
|
||||
}
|
||||
|
||||
@ -1280,7 +1299,7 @@ encode %{
|
||||
// preserve mark
|
||||
address mark = cbuf.insts()->mark();
|
||||
debug_only(int off0 = cbuf.insts_size());
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int ret_addr_offset = as_MachCall()->ret_addr_offset();
|
||||
__ adr(LR, mark + ret_addr_offset);
|
||||
__ str(LR, Address(Rthread, JavaThread::last_Java_pc_offset()));
|
||||
@ -1294,7 +1313,7 @@ encode %{
|
||||
// preserve mark
|
||||
address mark = cbuf.insts()->mark();
|
||||
debug_only(int off0 = cbuf.insts_size());
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
// FP is preserved across all calls, even compiled calls.
|
||||
// Use it to preserve SP in places where the callee might change the SP.
|
||||
__ mov(Rmh_SP_save, SP);
|
||||
@ -1305,12 +1324,12 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class restore_SP %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ mov(SP, Rmh_SP_save);
|
||||
%}
|
||||
|
||||
enc_class Java_Dynamic_Call (method meth) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode());
|
||||
assert(R8_ic_reg == Ricklass, "should be");
|
||||
__ set_inst_mark();
|
||||
@ -1338,7 +1357,7 @@ encode %{
|
||||
val |= (val << bit_width);
|
||||
}
|
||||
}
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
if (val == -1) {
|
||||
__ mvn($tmp$$Register, 0);
|
||||
@ -1355,7 +1374,7 @@ encode %{
|
||||
// Replicate float con 2 times and pack into vector (8 bytes) in regD.
|
||||
float fval = $src$$constant;
|
||||
int val = *((int*)&fval);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
if (val == -1) {
|
||||
__ mvn($tmp$$Register, 0);
|
||||
@ -1370,7 +1389,7 @@ encode %{
|
||||
|
||||
enc_class enc_String_Compare(R0RegP str1, R1RegP str2, R2RegI cnt1, R3RegI cnt2, iRegI result, iRegI tmp1, iRegI tmp2) %{
|
||||
Label Ldone, Lloop;
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
Register str1_reg = $str1$$Register;
|
||||
Register str2_reg = $str2$$Register;
|
||||
@ -1462,7 +1481,7 @@ encode %{
|
||||
|
||||
enc_class enc_String_Equals(R0RegP str1, R1RegP str2, R2RegI cnt, iRegI result, iRegI tmp1, iRegI tmp2) %{
|
||||
Label Lchar, Lchar_loop, Ldone, Lequal;
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
Register str1_reg = $str1$$Register;
|
||||
Register str2_reg = $str2$$Register;
|
||||
@ -1524,7 +1543,7 @@ encode %{
|
||||
|
||||
enc_class enc_Array_Equals(R0RegP ary1, R1RegP ary2, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI result) %{
|
||||
Label Ldone, Lloop, Lequal;
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
Register ary1_reg = $ary1$$Register;
|
||||
Register ary2_reg = $ary2$$Register;
|
||||
@ -2021,15 +2040,6 @@ operand immP0() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
operand immP_poll() %{
|
||||
predicate(n->get_ptr() != 0 && n->get_ptr() == (intptr_t)os::get_polling_page());
|
||||
match(ConP);
|
||||
|
||||
// formats are generated automatically for constants and base registers
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Pointer Immediate
|
||||
operand immN()
|
||||
%{
|
||||
@ -3098,12 +3108,6 @@ pipe_class loadConP( iRegP dst, immP src ) %{
|
||||
fixed_latency(6);
|
||||
%}
|
||||
|
||||
// Polling Address
|
||||
pipe_class loadConP_poll( iRegP dst, immP_poll src ) %{
|
||||
dst : E(write);
|
||||
IALU : R;
|
||||
%}
|
||||
|
||||
// Long Constant small
|
||||
pipe_class loadConLlo( iRegL dst, immL src ) %{
|
||||
instruction_count(2);
|
||||
@ -4286,16 +4290,6 @@ instruct loadConP(iRegP dst, immP src) %{
|
||||
%}
|
||||
|
||||
|
||||
instruct loadConP_poll(iRegP dst, immP_poll src) %{
|
||||
match(Set dst src);
|
||||
ins_cost(DEFAULT_COST);
|
||||
format %{ "MOV_SLOW $dst,$src\t!ptr" %}
|
||||
ins_encode %{
|
||||
__ mov_slow($dst$$Register, $src$$constant);
|
||||
%}
|
||||
ins_pipe(loadConP_poll);
|
||||
%}
|
||||
|
||||
instruct loadConL(iRegL dst, immL src) %{
|
||||
match(Set dst src);
|
||||
ins_cost(DEFAULT_COST * 4);
|
||||
|
160
src/hotspot/cpu/arm/c2_MacroAssembler_arm.cpp
Normal file
160
src/hotspot/cpu/arm/c2_MacroAssembler_arm.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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/assembler.hpp"
|
||||
#include "asm/assembler.inline.hpp"
|
||||
#include "opto/c2_MacroAssembler.hpp"
|
||||
#include "runtime/basicLock.hpp"
|
||||
|
||||
// TODO: 8 bytes at a time? pre-fetch?
|
||||
// Compare char[] arrays aligned to 4 bytes.
|
||||
void C2_MacroAssembler::char_arrays_equals(Register ary1, Register ary2,
|
||||
Register limit, Register result,
|
||||
Register chr1, Register chr2, Label& Ldone) {
|
||||
Label Lvector, Lloop;
|
||||
|
||||
// if (ary1 == ary2)
|
||||
// return true;
|
||||
cmpoop(ary1, ary2);
|
||||
b(Ldone, eq);
|
||||
|
||||
// Note: limit contains number of bytes (2*char_elements) != 0.
|
||||
tst(limit, 0x2); // trailing character ?
|
||||
b(Lvector, eq);
|
||||
|
||||
// compare the trailing char
|
||||
sub(limit, limit, sizeof(jchar));
|
||||
ldrh(chr1, Address(ary1, limit));
|
||||
ldrh(chr2, Address(ary2, limit));
|
||||
cmp(chr1, chr2);
|
||||
mov(result, 0, ne); // not equal
|
||||
b(Ldone, ne);
|
||||
|
||||
// only one char ?
|
||||
tst(limit, limit);
|
||||
mov(result, 1, eq);
|
||||
b(Ldone, eq);
|
||||
|
||||
// word by word compare, dont't need alignment check
|
||||
bind(Lvector);
|
||||
|
||||
// Shift ary1 and ary2 to the end of the arrays, negate limit
|
||||
add(ary1, limit, ary1);
|
||||
add(ary2, limit, ary2);
|
||||
neg(limit, limit);
|
||||
|
||||
bind(Lloop);
|
||||
ldr_u32(chr1, Address(ary1, limit));
|
||||
ldr_u32(chr2, Address(ary2, limit));
|
||||
cmp_32(chr1, chr2);
|
||||
mov(result, 0, ne); // not equal
|
||||
b(Ldone, ne);
|
||||
adds(limit, limit, 2*sizeof(jchar));
|
||||
b(Lloop, ne);
|
||||
|
||||
// Caller should set it:
|
||||
// mov(result_reg, 1); //equal
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::fast_lock(Register Roop, Register Rbox, Register Rscratch, Register Rscratch2, Register scratch3) {
|
||||
assert(VM_Version::supports_ldrex(), "unsupported, yet?");
|
||||
|
||||
Register Rmark = Rscratch2;
|
||||
|
||||
assert(Roop != Rscratch, "");
|
||||
assert(Roop != Rmark, "");
|
||||
assert(Rbox != Rscratch, "");
|
||||
assert(Rbox != Rmark, "");
|
||||
|
||||
Label fast_lock, done;
|
||||
|
||||
if (UseBiasedLocking && !UseOptoBiasInlining) {
|
||||
assert(scratch3 != noreg, "need extra temporary for -XX:-UseOptoBiasInlining");
|
||||
biased_locking_enter(Roop, Rmark, Rscratch, false, scratch3, done, done);
|
||||
// Fall through if lock not biased otherwise branch to done
|
||||
}
|
||||
|
||||
// Invariant: Rmark loaded below does not contain biased lock pattern
|
||||
|
||||
ldr(Rmark, Address(Roop, oopDesc::mark_offset_in_bytes()));
|
||||
tst(Rmark, markWord::unlocked_value);
|
||||
b(fast_lock, ne);
|
||||
|
||||
// Check for recursive lock
|
||||
// See comments in InterpreterMacroAssembler::lock_object for
|
||||
// explanations on the fast recursive locking check.
|
||||
// -1- test low 2 bits
|
||||
movs(Rscratch, AsmOperand(Rmark, lsl, 30));
|
||||
// -2- test (hdr - SP) if the low two bits are 0
|
||||
sub(Rscratch, Rmark, SP, eq);
|
||||
movs(Rscratch, AsmOperand(Rscratch, lsr, exact_log2(os::vm_page_size())), eq);
|
||||
// If still 'eq' then recursive locking OK
|
||||
// set to zero if recursive lock, set to non zero otherwise (see discussion in JDK-8153107)
|
||||
str(Rscratch, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
|
||||
b(done);
|
||||
|
||||
bind(fast_lock);
|
||||
str(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
|
||||
|
||||
bool allow_fallthrough_on_failure = true;
|
||||
bool one_shot = true;
|
||||
cas_for_lock_acquire(Rmark, Rbox, Roop, Rscratch, done, allow_fallthrough_on_failure, one_shot);
|
||||
|
||||
bind(done);
|
||||
|
||||
// At this point flags are set as follows:
|
||||
// EQ -> Success
|
||||
// NE -> Failure, branch to slow path
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::fast_unlock(Register Roop, Register Rbox, Register Rscratch, Register Rscratch2) {
|
||||
assert(VM_Version::supports_ldrex(), "unsupported, yet?");
|
||||
|
||||
Register Rmark = Rscratch2;
|
||||
|
||||
assert(Roop != Rscratch, "");
|
||||
assert(Roop != Rmark, "");
|
||||
assert(Rbox != Rscratch, "");
|
||||
assert(Rbox != Rmark, "");
|
||||
|
||||
Label done;
|
||||
|
||||
if (UseBiasedLocking && !UseOptoBiasInlining) {
|
||||
biased_locking_exit(Roop, Rscratch, done);
|
||||
}
|
||||
|
||||
ldr(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
|
||||
// If hdr is NULL, we've got recursive locking and there's nothing more to do
|
||||
cmp(Rmark, 0);
|
||||
b(done, eq);
|
||||
|
||||
// Restore the object header
|
||||
bool allow_fallthrough_on_failure = true;
|
||||
bool one_shot = true;
|
||||
cas_for_lock_release(Rmark, Rbox, Roop, Rscratch, done, allow_fallthrough_on_failure, one_shot);
|
||||
|
||||
bind(done);
|
||||
}
|
||||
|
39
src/hotspot/cpu/arm/c2_MacroAssembler_arm.hpp
Normal file
39
src/hotspot/cpu/arm/c2_MacroAssembler_arm.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CPU_ARM_C2_MACROASSEMBLER_ARM_HPP
|
||||
#define CPU_ARM_C2_MACROASSEMBLER_ARM_HPP
|
||||
|
||||
// C2_MacroAssembler contains high-level macros for C2
|
||||
|
||||
public:
|
||||
// Compare char[] arrays aligned to 4 bytes.
|
||||
void char_arrays_equals(Register ary1, Register ary2,
|
||||
Register limit, Register result,
|
||||
Register chr1, Register chr2, Label& Ldone);
|
||||
|
||||
void fast_lock(Register obj, Register box, Register scratch, Register scratch2, Register scratch3 = noreg);
|
||||
void fast_unlock(Register obj, Register box, Register scratch, Register scratch2);
|
||||
|
||||
#endif // CPU_ARM_C2_MACROASSEMBLER_ARM_HPP
|
@ -113,7 +113,7 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
||||
|
||||
sender_sp = _unextended_sp + _cb->frame_size();
|
||||
// Is sender_sp safe?
|
||||
if (!thread->is_in_full_stack((address)sender_sp)) {
|
||||
if (!thread->is_in_full_stack_checked((address)sender_sp)) {
|
||||
return false;
|
||||
}
|
||||
// With our calling conventions, the return_address should
|
||||
@ -223,13 +223,13 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
||||
|
||||
|
||||
void frame::patch_pc(Thread* thread, address pc) {
|
||||
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
|
||||
address* pc_addr = &((address *)sp())[-sender_sp_offset+return_addr_offset];
|
||||
if (TracePcPatching) {
|
||||
tty->print_cr("patch_pc at address" INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "] ",
|
||||
p2i(pc_addr), p2i(*pc_addr), p2i(pc));
|
||||
}
|
||||
*pc_addr = pc;
|
||||
_cb = CodeCache::find_blob(pc);
|
||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||
if (original_pc != NULL) {
|
||||
assert(original_pc == _pc, "expected original PC to be stored before patching");
|
||||
|
@ -62,6 +62,4 @@ const bool HaveVFP = true;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define THREAD_LOCAL_POLL
|
||||
|
||||
#endif // CPU_ARM_GLOBALDEFINITIONS_ARM_HPP
|
||||
|
@ -576,8 +576,7 @@ void InterpreterMacroAssembler::dispatch_base(TosState state,
|
||||
Label safepoint;
|
||||
address* const safepoint_table = Interpreter::safept_table(state);
|
||||
address* const table = Interpreter::dispatch_table(state);
|
||||
bool needs_thread_local_poll = generate_poll &&
|
||||
SafepointMechanism::uses_thread_local_poll() && table != safepoint_table;
|
||||
bool needs_thread_local_poll = generate_poll && table != safepoint_table;
|
||||
|
||||
if (needs_thread_local_poll) {
|
||||
NOT_PRODUCT(block_comment("Thread-local Safepoint poll"));
|
||||
|
@ -1626,57 +1626,6 @@ void MacroAssembler::lookup_interface_method(Register Rklass,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COMPILER2
|
||||
// TODO: 8 bytes at a time? pre-fetch?
|
||||
// Compare char[] arrays aligned to 4 bytes.
|
||||
void MacroAssembler::char_arrays_equals(Register ary1, Register ary2,
|
||||
Register limit, Register result,
|
||||
Register chr1, Register chr2, Label& Ldone) {
|
||||
Label Lvector, Lloop;
|
||||
|
||||
// if (ary1 == ary2)
|
||||
// return true;
|
||||
cmpoop(ary1, ary2);
|
||||
b(Ldone, eq);
|
||||
|
||||
// Note: limit contains number of bytes (2*char_elements) != 0.
|
||||
tst(limit, 0x2); // trailing character ?
|
||||
b(Lvector, eq);
|
||||
|
||||
// compare the trailing char
|
||||
sub(limit, limit, sizeof(jchar));
|
||||
ldrh(chr1, Address(ary1, limit));
|
||||
ldrh(chr2, Address(ary2, limit));
|
||||
cmp(chr1, chr2);
|
||||
mov(result, 0, ne); // not equal
|
||||
b(Ldone, ne);
|
||||
|
||||
// only one char ?
|
||||
tst(limit, limit);
|
||||
mov(result, 1, eq);
|
||||
b(Ldone, eq);
|
||||
|
||||
// word by word compare, dont't need alignment check
|
||||
bind(Lvector);
|
||||
|
||||
// Shift ary1 and ary2 to the end of the arrays, negate limit
|
||||
add(ary1, limit, ary1);
|
||||
add(ary2, limit, ary2);
|
||||
neg(limit, limit);
|
||||
|
||||
bind(Lloop);
|
||||
ldr_u32(chr1, Address(ary1, limit));
|
||||
ldr_u32(chr2, Address(ary2, limit));
|
||||
cmp_32(chr1, chr2);
|
||||
mov(result, 0, ne); // not equal
|
||||
b(Ldone, ne);
|
||||
adds(limit, limit, 2*sizeof(jchar));
|
||||
b(Lloop, ne);
|
||||
|
||||
// Caller should set it:
|
||||
// mov(result_reg, 1); //equal
|
||||
}
|
||||
#endif
|
||||
|
||||
void MacroAssembler::inc_counter(address counter_addr, Register tmpreg1, Register tmpreg2) {
|
||||
mov_slow(tmpreg1, counter_addr);
|
||||
@ -1970,110 +1919,14 @@ void MacroAssembler::resolve(DecoratorSet decorators, Register obj) {
|
||||
return bs->resolve(this, decorators, obj);
|
||||
}
|
||||
|
||||
|
||||
#ifdef COMPILER2
|
||||
void MacroAssembler::fast_lock(Register Roop, Register Rbox, Register Rscratch, Register Rscratch2, Register scratch3)
|
||||
{
|
||||
assert(VM_Version::supports_ldrex(), "unsupported, yet?");
|
||||
|
||||
Register Rmark = Rscratch2;
|
||||
|
||||
assert(Roop != Rscratch, "");
|
||||
assert(Roop != Rmark, "");
|
||||
assert(Rbox != Rscratch, "");
|
||||
assert(Rbox != Rmark, "");
|
||||
|
||||
Label fast_lock, done;
|
||||
|
||||
if (UseBiasedLocking && !UseOptoBiasInlining) {
|
||||
assert(scratch3 != noreg, "need extra temporary for -XX:-UseOptoBiasInlining");
|
||||
biased_locking_enter(Roop, Rmark, Rscratch, false, scratch3, done, done);
|
||||
// Fall through if lock not biased otherwise branch to done
|
||||
}
|
||||
|
||||
// Invariant: Rmark loaded below does not contain biased lock pattern
|
||||
|
||||
ldr(Rmark, Address(Roop, oopDesc::mark_offset_in_bytes()));
|
||||
tst(Rmark, markWord::unlocked_value);
|
||||
b(fast_lock, ne);
|
||||
|
||||
// Check for recursive lock
|
||||
// See comments in InterpreterMacroAssembler::lock_object for
|
||||
// explanations on the fast recursive locking check.
|
||||
// -1- test low 2 bits
|
||||
movs(Rscratch, AsmOperand(Rmark, lsl, 30));
|
||||
// -2- test (hdr - SP) if the low two bits are 0
|
||||
sub(Rscratch, Rmark, SP, eq);
|
||||
movs(Rscratch, AsmOperand(Rscratch, lsr, exact_log2(os::vm_page_size())), eq);
|
||||
// If still 'eq' then recursive locking OK
|
||||
// set to zero if recursive lock, set to non zero otherwise (see discussion in JDK-8153107)
|
||||
str(Rscratch, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
|
||||
b(done);
|
||||
|
||||
bind(fast_lock);
|
||||
str(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
|
||||
|
||||
bool allow_fallthrough_on_failure = true;
|
||||
bool one_shot = true;
|
||||
cas_for_lock_acquire(Rmark, Rbox, Roop, Rscratch, done, allow_fallthrough_on_failure, one_shot);
|
||||
|
||||
bind(done);
|
||||
|
||||
// At this point flags are set as follows:
|
||||
// EQ -> Success
|
||||
// NE -> Failure, branch to slow path
|
||||
}
|
||||
|
||||
void MacroAssembler::fast_unlock(Register Roop, Register Rbox, Register Rscratch, Register Rscratch2)
|
||||
{
|
||||
assert(VM_Version::supports_ldrex(), "unsupported, yet?");
|
||||
|
||||
Register Rmark = Rscratch2;
|
||||
|
||||
assert(Roop != Rscratch, "");
|
||||
assert(Roop != Rmark, "");
|
||||
assert(Rbox != Rscratch, "");
|
||||
assert(Rbox != Rmark, "");
|
||||
|
||||
Label done;
|
||||
|
||||
if (UseBiasedLocking && !UseOptoBiasInlining) {
|
||||
biased_locking_exit(Roop, Rscratch, done);
|
||||
}
|
||||
|
||||
ldr(Rmark, Address(Rbox, BasicLock::displaced_header_offset_in_bytes()));
|
||||
// If hdr is NULL, we've got recursive locking and there's nothing more to do
|
||||
cmp(Rmark, 0);
|
||||
b(done, eq);
|
||||
|
||||
// Restore the object header
|
||||
bool allow_fallthrough_on_failure = true;
|
||||
bool one_shot = true;
|
||||
cas_for_lock_release(Rmark, Rbox, Roop, Rscratch, done, allow_fallthrough_on_failure, one_shot);
|
||||
|
||||
bind(done);
|
||||
|
||||
}
|
||||
#endif // COMPILER2
|
||||
|
||||
void MacroAssembler::safepoint_poll(Register tmp1, Label& slow_path) {
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
ldr_u32(tmp1, Address(Rthread, Thread::polling_page_offset()));
|
||||
tst(tmp1, exact_log2(SafepointMechanism::poll_bit()));
|
||||
b(slow_path, eq);
|
||||
} else {
|
||||
ldr_global_s32(tmp1, SafepointSynchronize::address_of_state());
|
||||
cmp(tmp1, SafepointSynchronize::_not_synchronized);
|
||||
b(slow_path, ne);
|
||||
}
|
||||
ldr_u32(tmp1, Address(Rthread, Thread::polling_page_offset()));
|
||||
tst(tmp1, exact_log2(SafepointMechanism::poll_bit()));
|
||||
b(slow_path, eq);
|
||||
}
|
||||
|
||||
void MacroAssembler::get_polling_page(Register dest) {
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
ldr(dest, Address(Rthread, Thread::polling_page_offset()));
|
||||
} else {
|
||||
mov_address(dest, os::get_polling_page());
|
||||
}
|
||||
ldr(dest, Address(Rthread, Thread::polling_page_offset()));
|
||||
}
|
||||
|
||||
void MacroAssembler::read_polling_page(Register dest, relocInfo::relocType rtype) {
|
||||
|
@ -1068,11 +1068,6 @@ public:
|
||||
Register temp_reg2,
|
||||
Label& L_no_such_interface);
|
||||
|
||||
// Compare char[] arrays aligned to 4 bytes.
|
||||
void char_arrays_equals(Register ary1, Register ary2,
|
||||
Register limit, Register result,
|
||||
Register chr1, Register chr2, Label& Ldone);
|
||||
|
||||
|
||||
void floating_cmp(Register dst);
|
||||
|
||||
@ -1090,11 +1085,6 @@ public:
|
||||
|
||||
void restore_default_fp_mode();
|
||||
|
||||
#ifdef COMPILER2
|
||||
void fast_lock(Register obj, Register box, Register scratch, Register scratch2, Register scratch3 = noreg);
|
||||
void fast_unlock(Register obj, Register box, Register scratch, Register scratch2);
|
||||
#endif
|
||||
|
||||
void safepoint_poll(Register tmp1, Label& slow_path);
|
||||
void get_polling_page(Register dest);
|
||||
void read_polling_page(Register dest, relocInfo::relocType rtype);
|
||||
|
@ -1802,15 +1802,13 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
|
||||
__ reset_last_Java_frame(Rtemp); // Rtemp free since scratched by far call
|
||||
|
||||
if (!cause_return) {
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
// If our stashed return pc was modified by the runtime we avoid touching it
|
||||
__ ldr(R3_tmp, Address(Rthread, JavaThread::saved_exception_pc_offset()));
|
||||
__ ldr(R2_tmp, Address(SP, RegisterSaver::LR_offset * wordSize));
|
||||
__ cmp(R2_tmp, R3_tmp);
|
||||
// Adjust return pc forward to step over the safepoint poll instruction
|
||||
__ add(R2_tmp, R2_tmp, 4, eq);
|
||||
__ str(R2_tmp, Address(SP, RegisterSaver::LR_offset * wordSize), eq);
|
||||
}
|
||||
// If our stashed return pc was modified by the runtime we avoid touching it
|
||||
__ ldr(R3_tmp, Address(Rthread, JavaThread::saved_exception_pc_offset()));
|
||||
__ ldr(R2_tmp, Address(SP, RegisterSaver::LR_offset * wordSize));
|
||||
__ cmp(R2_tmp, R3_tmp);
|
||||
// Adjust return pc forward to step over the safepoint poll instruction
|
||||
__ add(R2_tmp, R2_tmp, 4, eq);
|
||||
__ str(R2_tmp, Address(SP, RegisterSaver::LR_offset * wordSize), eq);
|
||||
|
||||
// Check for pending exception
|
||||
__ ldr(Rtemp, Address(Rthread, Thread::pending_exception_offset()));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2019, SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -1335,11 +1335,7 @@ void LIR_Assembler::return_op(LIR_Opr result) {
|
||||
__ pop_frame();
|
||||
}
|
||||
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
__ ld(polling_page, in_bytes(Thread::polling_page_offset()), R16_thread);
|
||||
} else {
|
||||
__ load_const_optimized(polling_page, (long)(address) os::get_polling_page(), R0);
|
||||
}
|
||||
__ ld(polling_page, in_bytes(Thread::polling_page_offset()), R16_thread);
|
||||
|
||||
// Restore return pc relative to callers' sp.
|
||||
__ ld(return_pc, _abi(lr), R1_SP);
|
||||
@ -1362,11 +1358,7 @@ void LIR_Assembler::return_op(LIR_Opr result) {
|
||||
|
||||
int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) {
|
||||
const Register poll_addr = tmp->as_register();
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
__ ld(poll_addr, in_bytes(Thread::polling_page_offset()), R16_thread);
|
||||
} else {
|
||||
__ load_const_optimized(poll_addr, (intptr_t)os::get_polling_page(), R0);
|
||||
}
|
||||
__ ld(poll_addr, in_bytes(Thread::polling_page_offset()), R16_thread);
|
||||
if (info != NULL) {
|
||||
add_debug_info_for_branch(info);
|
||||
}
|
||||
|
580
src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp
Normal file
580
src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.cpp
Normal file
@ -0,0 +1,580 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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/assembler.hpp"
|
||||
#include "asm/assembler.inline.hpp"
|
||||
#include "opto/c2_MacroAssembler.hpp"
|
||||
#include "opto/intrinsicnode.hpp"
|
||||
|
||||
#ifdef PRODUCT
|
||||
#define BLOCK_COMMENT(str) // nothing
|
||||
#else
|
||||
#define BLOCK_COMMENT(str) block_comment(str)
|
||||
#endif
|
||||
#define BIND(label) bind(label); BLOCK_COMMENT(#label ":")
|
||||
|
||||
// Intrinsics for CompactStrings
|
||||
|
||||
// Compress char[] to byte[] by compressing 16 bytes at once.
|
||||
void C2_MacroAssembler::string_compress_16(Register src, Register dst, Register cnt,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5,
|
||||
Label& Lfailure) {
|
||||
|
||||
const Register tmp0 = R0;
|
||||
assert_different_registers(src, dst, cnt, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
|
||||
Label Lloop, Lslow;
|
||||
|
||||
// Check if cnt >= 8 (= 16 bytes)
|
||||
lis(tmp1, 0xFF); // tmp1 = 0x00FF00FF00FF00FF
|
||||
srwi_(tmp2, cnt, 3);
|
||||
beq(CCR0, Lslow);
|
||||
ori(tmp1, tmp1, 0xFF);
|
||||
rldimi(tmp1, tmp1, 32, 0);
|
||||
mtctr(tmp2);
|
||||
|
||||
// 2x unrolled loop
|
||||
bind(Lloop);
|
||||
ld(tmp2, 0, src); // _0_1_2_3 (Big Endian)
|
||||
ld(tmp4, 8, src); // _4_5_6_7
|
||||
|
||||
orr(tmp0, tmp2, tmp4);
|
||||
rldicl(tmp3, tmp2, 6*8, 64-24); // _____1_2
|
||||
rldimi(tmp2, tmp2, 2*8, 2*8); // _0_2_3_3
|
||||
rldicl(tmp5, tmp4, 6*8, 64-24); // _____5_6
|
||||
rldimi(tmp4, tmp4, 2*8, 2*8); // _4_6_7_7
|
||||
|
||||
andc_(tmp0, tmp0, tmp1);
|
||||
bne(CCR0, Lfailure); // Not latin1.
|
||||
addi(src, src, 16);
|
||||
|
||||
rlwimi(tmp3, tmp2, 0*8, 24, 31);// _____1_3
|
||||
srdi(tmp2, tmp2, 3*8); // ____0_2_
|
||||
rlwimi(tmp5, tmp4, 0*8, 24, 31);// _____5_7
|
||||
srdi(tmp4, tmp4, 3*8); // ____4_6_
|
||||
|
||||
orr(tmp2, tmp2, tmp3); // ____0123
|
||||
orr(tmp4, tmp4, tmp5); // ____4567
|
||||
|
||||
stw(tmp2, 0, dst);
|
||||
stw(tmp4, 4, dst);
|
||||
addi(dst, dst, 8);
|
||||
bdnz(Lloop);
|
||||
|
||||
bind(Lslow); // Fallback to slow version
|
||||
}
|
||||
|
||||
// Compress char[] to byte[]. cnt must be positive int.
|
||||
void C2_MacroAssembler::string_compress(Register src, Register dst, Register cnt, Register tmp, Label& Lfailure) {
|
||||
Label Lloop;
|
||||
mtctr(cnt);
|
||||
|
||||
bind(Lloop);
|
||||
lhz(tmp, 0, src);
|
||||
cmplwi(CCR0, tmp, 0xff);
|
||||
bgt(CCR0, Lfailure); // Not latin1.
|
||||
addi(src, src, 2);
|
||||
stb(tmp, 0, dst);
|
||||
addi(dst, dst, 1);
|
||||
bdnz(Lloop);
|
||||
}
|
||||
|
||||
// Inflate byte[] to char[] by inflating 16 bytes at once.
|
||||
void C2_MacroAssembler::string_inflate_16(Register src, Register dst, Register cnt,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5) {
|
||||
const Register tmp0 = R0;
|
||||
assert_different_registers(src, dst, cnt, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
|
||||
Label Lloop, Lslow;
|
||||
|
||||
// Check if cnt >= 8
|
||||
srwi_(tmp2, cnt, 3);
|
||||
beq(CCR0, Lslow);
|
||||
lis(tmp1, 0xFF); // tmp1 = 0x00FF00FF
|
||||
ori(tmp1, tmp1, 0xFF);
|
||||
mtctr(tmp2);
|
||||
|
||||
// 2x unrolled loop
|
||||
bind(Lloop);
|
||||
lwz(tmp2, 0, src); // ____0123 (Big Endian)
|
||||
lwz(tmp4, 4, src); // ____4567
|
||||
addi(src, src, 8);
|
||||
|
||||
rldicl(tmp3, tmp2, 7*8, 64-8); // _______2
|
||||
rlwimi(tmp2, tmp2, 3*8, 16, 23);// ____0113
|
||||
rldicl(tmp5, tmp4, 7*8, 64-8); // _______6
|
||||
rlwimi(tmp4, tmp4, 3*8, 16, 23);// ____4557
|
||||
|
||||
andc(tmp0, tmp2, tmp1); // ____0_1_
|
||||
rlwimi(tmp2, tmp3, 2*8, 0, 23); // _____2_3
|
||||
andc(tmp3, tmp4, tmp1); // ____4_5_
|
||||
rlwimi(tmp4, tmp5, 2*8, 0, 23); // _____6_7
|
||||
|
||||
rldimi(tmp2, tmp0, 3*8, 0*8); // _0_1_2_3
|
||||
rldimi(tmp4, tmp3, 3*8, 0*8); // _4_5_6_7
|
||||
|
||||
std(tmp2, 0, dst);
|
||||
std(tmp4, 8, dst);
|
||||
addi(dst, dst, 16);
|
||||
bdnz(Lloop);
|
||||
|
||||
bind(Lslow); // Fallback to slow version
|
||||
}
|
||||
|
||||
// Inflate byte[] to char[]. cnt must be positive int.
|
||||
void C2_MacroAssembler::string_inflate(Register src, Register dst, Register cnt, Register tmp) {
|
||||
Label Lloop;
|
||||
mtctr(cnt);
|
||||
|
||||
bind(Lloop);
|
||||
lbz(tmp, 0, src);
|
||||
addi(src, src, 1);
|
||||
sth(tmp, 0, dst);
|
||||
addi(dst, dst, 2);
|
||||
bdnz(Lloop);
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::string_compare(Register str1, Register str2,
|
||||
Register cnt1, Register cnt2,
|
||||
Register tmp1, Register result, int ae) {
|
||||
const Register tmp0 = R0,
|
||||
diff = tmp1;
|
||||
|
||||
assert_different_registers(str1, str2, cnt1, cnt2, tmp0, tmp1, result);
|
||||
Label Ldone, Lslow, Lloop, Lreturn_diff;
|
||||
|
||||
// Note: Making use of the fact that compareTo(a, b) == -compareTo(b, a)
|
||||
// we interchange str1 and str2 in the UL case and negate the result.
|
||||
// Like this, str1 is always latin1 encoded, except for the UU case.
|
||||
// In addition, we need 0 (or sign which is 0) extend.
|
||||
|
||||
if (ae == StrIntrinsicNode::UU) {
|
||||
srwi(cnt1, cnt1, 1);
|
||||
} else {
|
||||
clrldi(cnt1, cnt1, 32);
|
||||
}
|
||||
|
||||
if (ae != StrIntrinsicNode::LL) {
|
||||
srwi(cnt2, cnt2, 1);
|
||||
} else {
|
||||
clrldi(cnt2, cnt2, 32);
|
||||
}
|
||||
|
||||
// See if the lengths are different, and calculate min in cnt1.
|
||||
// Save diff in case we need it for a tie-breaker.
|
||||
subf_(diff, cnt2, cnt1); // diff = cnt1 - cnt2
|
||||
// if (diff > 0) { cnt1 = cnt2; }
|
||||
if (VM_Version::has_isel()) {
|
||||
isel(cnt1, CCR0, Assembler::greater, /*invert*/ false, cnt2);
|
||||
} else {
|
||||
Label Lskip;
|
||||
blt(CCR0, Lskip);
|
||||
mr(cnt1, cnt2);
|
||||
bind(Lskip);
|
||||
}
|
||||
|
||||
// Rename registers
|
||||
Register chr1 = result;
|
||||
Register chr2 = tmp0;
|
||||
|
||||
// Compare multiple characters in fast loop (only implemented for same encoding).
|
||||
int stride1 = 8, stride2 = 8;
|
||||
if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
|
||||
int log2_chars_per_iter = (ae == StrIntrinsicNode::LL) ? 3 : 2;
|
||||
Label Lfastloop, Lskipfast;
|
||||
|
||||
srwi_(tmp0, cnt1, log2_chars_per_iter);
|
||||
beq(CCR0, Lskipfast);
|
||||
rldicl(cnt2, cnt1, 0, 64 - log2_chars_per_iter); // Remaining characters.
|
||||
li(cnt1, 1 << log2_chars_per_iter); // Initialize for failure case: Rescan characters from current iteration.
|
||||
mtctr(tmp0);
|
||||
|
||||
bind(Lfastloop);
|
||||
ld(chr1, 0, str1);
|
||||
ld(chr2, 0, str2);
|
||||
cmpd(CCR0, chr1, chr2);
|
||||
bne(CCR0, Lslow);
|
||||
addi(str1, str1, stride1);
|
||||
addi(str2, str2, stride2);
|
||||
bdnz(Lfastloop);
|
||||
mr(cnt1, cnt2); // Remaining characters.
|
||||
bind(Lskipfast);
|
||||
}
|
||||
|
||||
// Loop which searches the first difference character by character.
|
||||
cmpwi(CCR0, cnt1, 0);
|
||||
beq(CCR0, Lreturn_diff);
|
||||
bind(Lslow);
|
||||
mtctr(cnt1);
|
||||
|
||||
switch (ae) {
|
||||
case StrIntrinsicNode::LL: stride1 = 1; stride2 = 1; break;
|
||||
case StrIntrinsicNode::UL: // fallthru (see comment above)
|
||||
case StrIntrinsicNode::LU: stride1 = 1; stride2 = 2; break;
|
||||
case StrIntrinsicNode::UU: stride1 = 2; stride2 = 2; break;
|
||||
default: ShouldNotReachHere(); break;
|
||||
}
|
||||
|
||||
bind(Lloop);
|
||||
if (stride1 == 1) { lbz(chr1, 0, str1); } else { lhz(chr1, 0, str1); }
|
||||
if (stride2 == 1) { lbz(chr2, 0, str2); } else { lhz(chr2, 0, str2); }
|
||||
subf_(result, chr2, chr1); // result = chr1 - chr2
|
||||
bne(CCR0, Ldone);
|
||||
addi(str1, str1, stride1);
|
||||
addi(str2, str2, stride2);
|
||||
bdnz(Lloop);
|
||||
|
||||
// If strings are equal up to min length, return the length difference.
|
||||
bind(Lreturn_diff);
|
||||
mr(result, diff);
|
||||
|
||||
// Otherwise, return the difference between the first mismatched chars.
|
||||
bind(Ldone);
|
||||
if (ae == StrIntrinsicNode::UL) {
|
||||
neg(result, result); // Negate result (see note above).
|
||||
}
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::array_equals(bool is_array_equ, Register ary1, Register ary2,
|
||||
Register limit, Register tmp1, Register result, bool is_byte) {
|
||||
const Register tmp0 = R0;
|
||||
assert_different_registers(ary1, ary2, limit, tmp0, tmp1, result);
|
||||
Label Ldone, Lskiploop, Lloop, Lfastloop, Lskipfast;
|
||||
bool limit_needs_shift = false;
|
||||
|
||||
if (is_array_equ) {
|
||||
const int length_offset = arrayOopDesc::length_offset_in_bytes();
|
||||
const int base_offset = arrayOopDesc::base_offset_in_bytes(is_byte ? T_BYTE : T_CHAR);
|
||||
|
||||
// Return true if the same array.
|
||||
cmpd(CCR0, ary1, ary2);
|
||||
beq(CCR0, Lskiploop);
|
||||
|
||||
// Return false if one of them is NULL.
|
||||
cmpdi(CCR0, ary1, 0);
|
||||
cmpdi(CCR1, ary2, 0);
|
||||
li(result, 0);
|
||||
cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
|
||||
beq(CCR0, Ldone);
|
||||
|
||||
// Load the lengths of arrays.
|
||||
lwz(limit, length_offset, ary1);
|
||||
lwz(tmp0, length_offset, ary2);
|
||||
|
||||
// Return false if the two arrays are not equal length.
|
||||
cmpw(CCR0, limit, tmp0);
|
||||
bne(CCR0, Ldone);
|
||||
|
||||
// Load array addresses.
|
||||
addi(ary1, ary1, base_offset);
|
||||
addi(ary2, ary2, base_offset);
|
||||
} else {
|
||||
limit_needs_shift = !is_byte;
|
||||
li(result, 0); // Assume not equal.
|
||||
}
|
||||
|
||||
// Rename registers
|
||||
Register chr1 = tmp0;
|
||||
Register chr2 = tmp1;
|
||||
|
||||
// Compare 8 bytes per iteration in fast loop.
|
||||
const int log2_chars_per_iter = is_byte ? 3 : 2;
|
||||
|
||||
srwi_(tmp0, limit, log2_chars_per_iter + (limit_needs_shift ? 1 : 0));
|
||||
beq(CCR0, Lskipfast);
|
||||
mtctr(tmp0);
|
||||
|
||||
bind(Lfastloop);
|
||||
ld(chr1, 0, ary1);
|
||||
ld(chr2, 0, ary2);
|
||||
addi(ary1, ary1, 8);
|
||||
addi(ary2, ary2, 8);
|
||||
cmpd(CCR0, chr1, chr2);
|
||||
bne(CCR0, Ldone);
|
||||
bdnz(Lfastloop);
|
||||
|
||||
bind(Lskipfast);
|
||||
rldicl_(limit, limit, limit_needs_shift ? 64 - 1 : 0, 64 - log2_chars_per_iter); // Remaining characters.
|
||||
beq(CCR0, Lskiploop);
|
||||
mtctr(limit);
|
||||
|
||||
// Character by character.
|
||||
bind(Lloop);
|
||||
if (is_byte) {
|
||||
lbz(chr1, 0, ary1);
|
||||
lbz(chr2, 0, ary2);
|
||||
addi(ary1, ary1, 1);
|
||||
addi(ary2, ary2, 1);
|
||||
} else {
|
||||
lhz(chr1, 0, ary1);
|
||||
lhz(chr2, 0, ary2);
|
||||
addi(ary1, ary1, 2);
|
||||
addi(ary2, ary2, 2);
|
||||
}
|
||||
cmpw(CCR0, chr1, chr2);
|
||||
bne(CCR0, Ldone);
|
||||
bdnz(Lloop);
|
||||
|
||||
bind(Lskiploop);
|
||||
li(result, 1); // All characters are equal.
|
||||
bind(Ldone);
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::string_indexof(Register result, Register haystack, Register haycnt,
|
||||
Register needle, ciTypeArray* needle_values, Register needlecnt, int needlecntval,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4, int ae) {
|
||||
|
||||
// Ensure 0<needlecnt<=haycnt in ideal graph as prerequisite!
|
||||
Label L_TooShort, L_Found, L_NotFound, L_End;
|
||||
Register last_addr = haycnt, // Kill haycnt at the beginning.
|
||||
addr = tmp1,
|
||||
n_start = tmp2,
|
||||
ch1 = tmp3,
|
||||
ch2 = R0;
|
||||
|
||||
assert(ae != StrIntrinsicNode::LU, "Invalid encoding");
|
||||
const int h_csize = (ae == StrIntrinsicNode::LL) ? 1 : 2;
|
||||
const int n_csize = (ae == StrIntrinsicNode::UU) ? 2 : 1;
|
||||
|
||||
// **************************************************************************************************
|
||||
// Prepare for main loop: optimized for needle count >=2, bail out otherwise.
|
||||
// **************************************************************************************************
|
||||
|
||||
// Compute last haystack addr to use if no match gets found.
|
||||
clrldi(haycnt, haycnt, 32); // Ensure positive int is valid as 64 bit value.
|
||||
addi(addr, haystack, -h_csize); // Accesses use pre-increment.
|
||||
if (needlecntval == 0) { // variable needlecnt
|
||||
cmpwi(CCR6, needlecnt, 2);
|
||||
clrldi(needlecnt, needlecnt, 32); // Ensure positive int is valid as 64 bit value.
|
||||
blt(CCR6, L_TooShort); // Variable needlecnt: handle short needle separately.
|
||||
}
|
||||
|
||||
if (n_csize == 2) { lwz(n_start, 0, needle); } else { lhz(n_start, 0, needle); } // Load first 2 characters of needle.
|
||||
|
||||
if (needlecntval == 0) { // variable needlecnt
|
||||
subf(ch1, needlecnt, haycnt); // Last character index to compare is haycnt-needlecnt.
|
||||
addi(needlecnt, needlecnt, -2); // Rest of needle.
|
||||
} else { // constant needlecnt
|
||||
guarantee(needlecntval != 1, "IndexOf with single-character needle must be handled separately");
|
||||
assert((needlecntval & 0x7fff) == needlecntval, "wrong immediate");
|
||||
addi(ch1, haycnt, -needlecntval); // Last character index to compare is haycnt-needlecnt.
|
||||
if (needlecntval > 3) { li(needlecnt, needlecntval - 2); } // Rest of needle.
|
||||
}
|
||||
|
||||
if (h_csize == 2) { slwi(ch1, ch1, 1); } // Scale to number of bytes.
|
||||
|
||||
if (ae ==StrIntrinsicNode::UL) {
|
||||
srwi(tmp4, n_start, 1*8); // ___0
|
||||
rlwimi(n_start, tmp4, 2*8, 0, 23); // _0_1
|
||||
}
|
||||
|
||||
add(last_addr, haystack, ch1); // Point to last address to compare (haystack+2*(haycnt-needlecnt)).
|
||||
|
||||
// Main Loop (now we have at least 2 characters).
|
||||
Label L_OuterLoop, L_InnerLoop, L_FinalCheck, L_Comp1, L_Comp2;
|
||||
bind(L_OuterLoop); // Search for 1st 2 characters.
|
||||
Register addr_diff = tmp4;
|
||||
subf(addr_diff, addr, last_addr); // Difference between already checked address and last address to check.
|
||||
addi(addr, addr, h_csize); // This is the new address we want to use for comparing.
|
||||
srdi_(ch2, addr_diff, h_csize);
|
||||
beq(CCR0, L_FinalCheck); // 2 characters left?
|
||||
mtctr(ch2); // num of characters / 2
|
||||
bind(L_InnerLoop); // Main work horse (2x unrolled search loop)
|
||||
if (h_csize == 2) { // Load 2 characters of haystack (ignore alignment).
|
||||
lwz(ch1, 0, addr);
|
||||
lwz(ch2, 2, addr);
|
||||
} else {
|
||||
lhz(ch1, 0, addr);
|
||||
lhz(ch2, 1, addr);
|
||||
}
|
||||
cmpw(CCR0, ch1, n_start); // Compare 2 characters (1 would be sufficient but try to reduce branches to CompLoop).
|
||||
cmpw(CCR1, ch2, n_start);
|
||||
beq(CCR0, L_Comp1); // Did we find the needle start?
|
||||
beq(CCR1, L_Comp2);
|
||||
addi(addr, addr, 2 * h_csize);
|
||||
bdnz(L_InnerLoop);
|
||||
bind(L_FinalCheck);
|
||||
andi_(addr_diff, addr_diff, h_csize); // Remaining characters not covered by InnerLoop: (num of characters) & 1.
|
||||
beq(CCR0, L_NotFound);
|
||||
if (h_csize == 2) { lwz(ch1, 0, addr); } else { lhz(ch1, 0, addr); } // One position left at which we have to compare.
|
||||
cmpw(CCR1, ch1, n_start);
|
||||
beq(CCR1, L_Comp1);
|
||||
bind(L_NotFound);
|
||||
li(result, -1); // not found
|
||||
b(L_End);
|
||||
|
||||
// **************************************************************************************************
|
||||
// Special Case: unfortunately, the variable needle case can be called with needlecnt<2
|
||||
// **************************************************************************************************
|
||||
if (needlecntval == 0) { // We have to handle these cases separately.
|
||||
Label L_OneCharLoop;
|
||||
bind(L_TooShort);
|
||||
mtctr(haycnt);
|
||||
if (n_csize == 2) { lhz(n_start, 0, needle); } else { lbz(n_start, 0, needle); } // First character of needle
|
||||
bind(L_OneCharLoop);
|
||||
if (h_csize == 2) { lhzu(ch1, 2, addr); } else { lbzu(ch1, 1, addr); }
|
||||
cmpw(CCR1, ch1, n_start);
|
||||
beq(CCR1, L_Found); // Did we find the one character needle?
|
||||
bdnz(L_OneCharLoop);
|
||||
li(result, -1); // Not found.
|
||||
b(L_End);
|
||||
}
|
||||
|
||||
// **************************************************************************************************
|
||||
// Regular Case Part II: compare rest of needle (first 2 characters have been compared already)
|
||||
// **************************************************************************************************
|
||||
|
||||
// Compare the rest
|
||||
bind(L_Comp2);
|
||||
addi(addr, addr, h_csize); // First comparison has failed, 2nd one hit.
|
||||
bind(L_Comp1); // Addr points to possible needle start.
|
||||
if (needlecntval != 2) { // Const needlecnt==2?
|
||||
if (needlecntval != 3) {
|
||||
if (needlecntval == 0) { beq(CCR6, L_Found); } // Variable needlecnt==2?
|
||||
Register n_ind = tmp4,
|
||||
h_ind = n_ind;
|
||||
li(n_ind, 2 * n_csize); // First 2 characters are already compared, use index 2.
|
||||
mtctr(needlecnt); // Decremented by 2, still > 0.
|
||||
Label L_CompLoop;
|
||||
bind(L_CompLoop);
|
||||
if (ae ==StrIntrinsicNode::UL) {
|
||||
h_ind = ch1;
|
||||
sldi(h_ind, n_ind, 1);
|
||||
}
|
||||
if (n_csize == 2) { lhzx(ch2, needle, n_ind); } else { lbzx(ch2, needle, n_ind); }
|
||||
if (h_csize == 2) { lhzx(ch1, addr, h_ind); } else { lbzx(ch1, addr, h_ind); }
|
||||
cmpw(CCR1, ch1, ch2);
|
||||
bne(CCR1, L_OuterLoop);
|
||||
addi(n_ind, n_ind, n_csize);
|
||||
bdnz(L_CompLoop);
|
||||
} else { // No loop required if there's only one needle character left.
|
||||
if (n_csize == 2) { lhz(ch2, 2 * 2, needle); } else { lbz(ch2, 2 * 1, needle); }
|
||||
if (h_csize == 2) { lhz(ch1, 2 * 2, addr); } else { lbz(ch1, 2 * 1, addr); }
|
||||
cmpw(CCR1, ch1, ch2);
|
||||
bne(CCR1, L_OuterLoop);
|
||||
}
|
||||
}
|
||||
// Return index ...
|
||||
bind(L_Found);
|
||||
subf(result, haystack, addr); // relative to haystack, ...
|
||||
if (h_csize == 2) { srdi(result, result, 1); } // in characters.
|
||||
bind(L_End);
|
||||
} // string_indexof
|
||||
|
||||
void C2_MacroAssembler::string_indexof_char(Register result, Register haystack, Register haycnt,
|
||||
Register needle, jchar needleChar, Register tmp1, Register tmp2, bool is_byte) {
|
||||
assert_different_registers(haystack, haycnt, needle, tmp1, tmp2);
|
||||
|
||||
Label L_InnerLoop, L_FinalCheck, L_Found1, L_Found2, L_NotFound, L_End;
|
||||
Register addr = tmp1,
|
||||
ch1 = tmp2,
|
||||
ch2 = R0;
|
||||
|
||||
const int h_csize = is_byte ? 1 : 2;
|
||||
|
||||
//4:
|
||||
srwi_(tmp2, haycnt, 1); // Shift right by exact_log2(UNROLL_FACTOR).
|
||||
mr(addr, haystack);
|
||||
beq(CCR0, L_FinalCheck);
|
||||
mtctr(tmp2); // Move to count register.
|
||||
//8:
|
||||
bind(L_InnerLoop); // Main work horse (2x unrolled search loop).
|
||||
if (!is_byte) {
|
||||
lhz(ch1, 0, addr);
|
||||
lhz(ch2, 2, addr);
|
||||
} else {
|
||||
lbz(ch1, 0, addr);
|
||||
lbz(ch2, 1, addr);
|
||||
}
|
||||
(needle != R0) ? cmpw(CCR0, ch1, needle) : cmplwi(CCR0, ch1, (unsigned int)needleChar);
|
||||
(needle != R0) ? cmpw(CCR1, ch2, needle) : cmplwi(CCR1, ch2, (unsigned int)needleChar);
|
||||
beq(CCR0, L_Found1); // Did we find the needle?
|
||||
beq(CCR1, L_Found2);
|
||||
addi(addr, addr, 2 * h_csize);
|
||||
bdnz(L_InnerLoop);
|
||||
//16:
|
||||
bind(L_FinalCheck);
|
||||
andi_(R0, haycnt, 1);
|
||||
beq(CCR0, L_NotFound);
|
||||
if (!is_byte) { lhz(ch1, 0, addr); } else { lbz(ch1, 0, addr); } // One position left at which we have to compare.
|
||||
(needle != R0) ? cmpw(CCR1, ch1, needle) : cmplwi(CCR1, ch1, (unsigned int)needleChar);
|
||||
beq(CCR1, L_Found1);
|
||||
//21:
|
||||
bind(L_NotFound);
|
||||
li(result, -1); // Not found.
|
||||
b(L_End);
|
||||
|
||||
bind(L_Found2);
|
||||
addi(addr, addr, h_csize);
|
||||
//24:
|
||||
bind(L_Found1); // Return index ...
|
||||
subf(result, haystack, addr); // relative to haystack, ...
|
||||
if (!is_byte) { srdi(result, result, 1); } // in characters.
|
||||
bind(L_End);
|
||||
} // string_indexof_char
|
||||
|
||||
|
||||
void C2_MacroAssembler::has_negatives(Register src, Register cnt, Register result,
|
||||
Register tmp1, Register tmp2) {
|
||||
const Register tmp0 = R0;
|
||||
assert_different_registers(src, result, cnt, tmp0, tmp1, tmp2);
|
||||
Label Lfastloop, Lslow, Lloop, Lnoneg, Ldone;
|
||||
|
||||
// Check if cnt >= 8 (= 16 bytes)
|
||||
lis(tmp1, (int)(short)0x8080); // tmp1 = 0x8080808080808080
|
||||
srwi_(tmp2, cnt, 4);
|
||||
li(result, 1); // Assume there's a negative byte.
|
||||
beq(CCR0, Lslow);
|
||||
ori(tmp1, tmp1, 0x8080);
|
||||
rldimi(tmp1, tmp1, 32, 0);
|
||||
mtctr(tmp2);
|
||||
|
||||
// 2x unrolled loop
|
||||
bind(Lfastloop);
|
||||
ld(tmp2, 0, src);
|
||||
ld(tmp0, 8, src);
|
||||
|
||||
orr(tmp0, tmp2, tmp0);
|
||||
|
||||
and_(tmp0, tmp0, tmp1);
|
||||
bne(CCR0, Ldone); // Found negative byte.
|
||||
addi(src, src, 16);
|
||||
|
||||
bdnz(Lfastloop);
|
||||
|
||||
bind(Lslow); // Fallback to slow version
|
||||
rldicl_(tmp0, cnt, 0, 64-4);
|
||||
beq(CCR0, Lnoneg);
|
||||
mtctr(tmp0);
|
||||
bind(Lloop);
|
||||
lbz(tmp0, 0, src);
|
||||
addi(src, src, 1);
|
||||
andi_(tmp0, tmp0, 0x80);
|
||||
bne(CCR0, Ldone); // Found negative byte.
|
||||
bdnz(Lloop);
|
||||
bind(Lnoneg);
|
||||
li(result, 0);
|
||||
|
||||
bind(Ldone);
|
||||
}
|
||||
|
62
src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.hpp
Normal file
62
src/hotspot/cpu/ppc/c2_MacroAssembler_ppc.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CPU_PPC_C2_MACROASSEMBLER_PPC_HPP
|
||||
#define CPU_PPC_C2_MACROASSEMBLER_PPC_HPP
|
||||
|
||||
// C2_MacroAssembler contains high-level macros for C2
|
||||
|
||||
public:
|
||||
// Intrinsics for CompactStrings
|
||||
// Compress char[] to byte[] by compressing 16 bytes at once.
|
||||
void string_compress_16(Register src, Register dst, Register cnt,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5,
|
||||
Label& Lfailure);
|
||||
|
||||
// Compress char[] to byte[]. cnt must be positive int.
|
||||
void string_compress(Register src, Register dst, Register cnt, Register tmp, Label& Lfailure);
|
||||
|
||||
// Inflate byte[] to char[] by inflating 16 bytes at once.
|
||||
void string_inflate_16(Register src, Register dst, Register cnt,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5);
|
||||
|
||||
// Inflate byte[] to char[]. cnt must be positive int.
|
||||
void string_inflate(Register src, Register dst, Register cnt, Register tmp);
|
||||
|
||||
void string_compare(Register str1, Register str2, Register cnt1, Register cnt2,
|
||||
Register tmp1, Register result, int ae);
|
||||
|
||||
void array_equals(bool is_array_equ, Register ary1, Register ary2,
|
||||
Register limit, Register tmp1, Register result, bool is_byte);
|
||||
|
||||
void string_indexof(Register result, Register haystack, Register haycnt,
|
||||
Register needle, ciTypeArray* needle_values, Register needlecnt, int needlecntval,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4, int ae);
|
||||
|
||||
void string_indexof_char(Register result, Register haystack, Register haycnt,
|
||||
Register needle, jchar needleChar, Register tmp1, Register tmp2, bool is_byte);
|
||||
|
||||
void has_negatives(Register src, Register cnt, Register result, Register tmp1, Register tmp2);
|
||||
|
||||
#endif // CPU_PPC_C2_MACROASSEMBLER_PPC_HPP
|
@ -62,7 +62,7 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
||||
}
|
||||
|
||||
// Unextended sp must be within the stack
|
||||
if (!thread->is_in_full_stack(unextended_sp)) {
|
||||
if (!thread->is_in_full_stack_checked(unextended_sp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -247,12 +247,12 @@ frame frame::sender(RegisterMap* map) const {
|
||||
}
|
||||
|
||||
void frame::patch_pc(Thread* thread, address pc) {
|
||||
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
|
||||
if (TracePcPatching) {
|
||||
tty->print_cr("patch_pc at address " PTR_FORMAT " [" PTR_FORMAT " -> " PTR_FORMAT "]",
|
||||
p2i(&((address*) _sp)[-1]), p2i(((address*) _sp)[-1]), p2i(pc));
|
||||
}
|
||||
own_abi()->lr = (uint64_t)pc;
|
||||
_cb = CodeCache::find_blob(pc);
|
||||
if (_cb != NULL && _cb->is_nmethod() && ((nmethod*)_cb)->is_deopt_pc(_pc)) {
|
||||
address orig = (((nmethod*)_cb)->get_original_pc(this));
|
||||
assert(orig == _pc, "expected original to be stored before patching");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2016 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -64,7 +64,6 @@ const bool CCallingConventionRequiresIntsAsLongs = true;
|
||||
|
||||
#define SUPPORT_RESERVED_STACK_AREA
|
||||
|
||||
#define THREAD_LOCAL_POLL
|
||||
// If UseSIGTRAP is active, we only use the poll bit and no polling page.
|
||||
// Otherwise, we fall back to usage of the polling page in nmethods.
|
||||
// Define the condition to use this -XX flag.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -218,7 +218,7 @@ void InterpreterMacroAssembler::dispatch_Lbyte_code(TosState state, Register byt
|
||||
// Calc dispatch table address.
|
||||
load_dispatch_table(R11_scratch1, table);
|
||||
|
||||
if (SafepointMechanism::uses_thread_local_poll() && generate_poll) {
|
||||
if (generate_poll) {
|
||||
address *sfpt_tbl = Interpreter::safept_table(state);
|
||||
if (table != sfpt_tbl) {
|
||||
Label dispatch;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2019, SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -33,6 +33,7 @@
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "nativeInst_ppc.hpp"
|
||||
#include "oops/klass.inline.hpp"
|
||||
#include "oops/methodData.hpp"
|
||||
#include "prims/methodHandles.hpp"
|
||||
#include "runtime/biasedLocking.hpp"
|
||||
#include "runtime/icache.hpp"
|
||||
@ -45,9 +46,6 @@
|
||||
#include "runtime/stubRoutines.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
#ifdef COMPILER2
|
||||
#include "opto/intrinsicnode.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef PRODUCT
|
||||
#define BLOCK_COMMENT(str) // nothing
|
||||
@ -1296,7 +1294,7 @@ bool MacroAssembler::is_load_from_polling_page(int instruction, void* ucontext,
|
||||
if (polling_address_ptr != NULL) {
|
||||
*polling_address_ptr = addr;
|
||||
}
|
||||
return os::is_poll_address(addr);
|
||||
return SafepointMechanism::is_poll_address(addr);
|
||||
#else
|
||||
// Not on Linux, ucontext must be NULL.
|
||||
ShouldNotReachHere();
|
||||
@ -3039,14 +3037,9 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe
|
||||
}
|
||||
|
||||
void MacroAssembler::safepoint_poll(Label& slow_path, Register temp_reg) {
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
ld(temp_reg, in_bytes(Thread::polling_page_offset()), R16_thread);
|
||||
// Armed page has poll_bit set.
|
||||
andi_(temp_reg, temp_reg, SafepointMechanism::poll_bit());
|
||||
} else {
|
||||
lwz(temp_reg, (RegisterOrConstant)(intptr_t)SafepointSynchronize::address_of_state());
|
||||
cmpwi(CCR0, temp_reg, SafepointSynchronize::_not_synchronized);
|
||||
}
|
||||
ld(temp_reg, in_bytes(Thread::polling_page_offset()), R16_thread);
|
||||
// Armed page has poll_bit set.
|
||||
andi_(temp_reg, temp_reg, SafepointMechanism::poll_bit());
|
||||
bne(CCR0, slow_path);
|
||||
}
|
||||
|
||||
@ -3311,552 +3304,6 @@ void MacroAssembler::clear_memory_doubleword(Register base_ptr, Register cnt_dwo
|
||||
|
||||
/////////////////////////////////////////// String intrinsics ////////////////////////////////////////////
|
||||
|
||||
#ifdef COMPILER2
|
||||
// Intrinsics for CompactStrings
|
||||
|
||||
// Compress char[] to byte[] by compressing 16 bytes at once.
|
||||
void MacroAssembler::string_compress_16(Register src, Register dst, Register cnt,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5,
|
||||
Label& Lfailure) {
|
||||
|
||||
const Register tmp0 = R0;
|
||||
assert_different_registers(src, dst, cnt, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
|
||||
Label Lloop, Lslow;
|
||||
|
||||
// Check if cnt >= 8 (= 16 bytes)
|
||||
lis(tmp1, 0xFF); // tmp1 = 0x00FF00FF00FF00FF
|
||||
srwi_(tmp2, cnt, 3);
|
||||
beq(CCR0, Lslow);
|
||||
ori(tmp1, tmp1, 0xFF);
|
||||
rldimi(tmp1, tmp1, 32, 0);
|
||||
mtctr(tmp2);
|
||||
|
||||
// 2x unrolled loop
|
||||
bind(Lloop);
|
||||
ld(tmp2, 0, src); // _0_1_2_3 (Big Endian)
|
||||
ld(tmp4, 8, src); // _4_5_6_7
|
||||
|
||||
orr(tmp0, tmp2, tmp4);
|
||||
rldicl(tmp3, tmp2, 6*8, 64-24); // _____1_2
|
||||
rldimi(tmp2, tmp2, 2*8, 2*8); // _0_2_3_3
|
||||
rldicl(tmp5, tmp4, 6*8, 64-24); // _____5_6
|
||||
rldimi(tmp4, tmp4, 2*8, 2*8); // _4_6_7_7
|
||||
|
||||
andc_(tmp0, tmp0, tmp1);
|
||||
bne(CCR0, Lfailure); // Not latin1.
|
||||
addi(src, src, 16);
|
||||
|
||||
rlwimi(tmp3, tmp2, 0*8, 24, 31);// _____1_3
|
||||
srdi(tmp2, tmp2, 3*8); // ____0_2_
|
||||
rlwimi(tmp5, tmp4, 0*8, 24, 31);// _____5_7
|
||||
srdi(tmp4, tmp4, 3*8); // ____4_6_
|
||||
|
||||
orr(tmp2, tmp2, tmp3); // ____0123
|
||||
orr(tmp4, tmp4, tmp5); // ____4567
|
||||
|
||||
stw(tmp2, 0, dst);
|
||||
stw(tmp4, 4, dst);
|
||||
addi(dst, dst, 8);
|
||||
bdnz(Lloop);
|
||||
|
||||
bind(Lslow); // Fallback to slow version
|
||||
}
|
||||
|
||||
// Compress char[] to byte[]. cnt must be positive int.
|
||||
void MacroAssembler::string_compress(Register src, Register dst, Register cnt, Register tmp, Label& Lfailure) {
|
||||
Label Lloop;
|
||||
mtctr(cnt);
|
||||
|
||||
bind(Lloop);
|
||||
lhz(tmp, 0, src);
|
||||
cmplwi(CCR0, tmp, 0xff);
|
||||
bgt(CCR0, Lfailure); // Not latin1.
|
||||
addi(src, src, 2);
|
||||
stb(tmp, 0, dst);
|
||||
addi(dst, dst, 1);
|
||||
bdnz(Lloop);
|
||||
}
|
||||
|
||||
// Inflate byte[] to char[] by inflating 16 bytes at once.
|
||||
void MacroAssembler::string_inflate_16(Register src, Register dst, Register cnt,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5) {
|
||||
const Register tmp0 = R0;
|
||||
assert_different_registers(src, dst, cnt, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5);
|
||||
Label Lloop, Lslow;
|
||||
|
||||
// Check if cnt >= 8
|
||||
srwi_(tmp2, cnt, 3);
|
||||
beq(CCR0, Lslow);
|
||||
lis(tmp1, 0xFF); // tmp1 = 0x00FF00FF
|
||||
ori(tmp1, tmp1, 0xFF);
|
||||
mtctr(tmp2);
|
||||
|
||||
// 2x unrolled loop
|
||||
bind(Lloop);
|
||||
lwz(tmp2, 0, src); // ____0123 (Big Endian)
|
||||
lwz(tmp4, 4, src); // ____4567
|
||||
addi(src, src, 8);
|
||||
|
||||
rldicl(tmp3, tmp2, 7*8, 64-8); // _______2
|
||||
rlwimi(tmp2, tmp2, 3*8, 16, 23);// ____0113
|
||||
rldicl(tmp5, tmp4, 7*8, 64-8); // _______6
|
||||
rlwimi(tmp4, tmp4, 3*8, 16, 23);// ____4557
|
||||
|
||||
andc(tmp0, tmp2, tmp1); // ____0_1_
|
||||
rlwimi(tmp2, tmp3, 2*8, 0, 23); // _____2_3
|
||||
andc(tmp3, tmp4, tmp1); // ____4_5_
|
||||
rlwimi(tmp4, tmp5, 2*8, 0, 23); // _____6_7
|
||||
|
||||
rldimi(tmp2, tmp0, 3*8, 0*8); // _0_1_2_3
|
||||
rldimi(tmp4, tmp3, 3*8, 0*8); // _4_5_6_7
|
||||
|
||||
std(tmp2, 0, dst);
|
||||
std(tmp4, 8, dst);
|
||||
addi(dst, dst, 16);
|
||||
bdnz(Lloop);
|
||||
|
||||
bind(Lslow); // Fallback to slow version
|
||||
}
|
||||
|
||||
// Inflate byte[] to char[]. cnt must be positive int.
|
||||
void MacroAssembler::string_inflate(Register src, Register dst, Register cnt, Register tmp) {
|
||||
Label Lloop;
|
||||
mtctr(cnt);
|
||||
|
||||
bind(Lloop);
|
||||
lbz(tmp, 0, src);
|
||||
addi(src, src, 1);
|
||||
sth(tmp, 0, dst);
|
||||
addi(dst, dst, 2);
|
||||
bdnz(Lloop);
|
||||
}
|
||||
|
||||
void MacroAssembler::string_compare(Register str1, Register str2,
|
||||
Register cnt1, Register cnt2,
|
||||
Register tmp1, Register result, int ae) {
|
||||
const Register tmp0 = R0,
|
||||
diff = tmp1;
|
||||
|
||||
assert_different_registers(str1, str2, cnt1, cnt2, tmp0, tmp1, result);
|
||||
Label Ldone, Lslow, Lloop, Lreturn_diff;
|
||||
|
||||
// Note: Making use of the fact that compareTo(a, b) == -compareTo(b, a)
|
||||
// we interchange str1 and str2 in the UL case and negate the result.
|
||||
// Like this, str1 is always latin1 encoded, except for the UU case.
|
||||
// In addition, we need 0 (or sign which is 0) extend.
|
||||
|
||||
if (ae == StrIntrinsicNode::UU) {
|
||||
srwi(cnt1, cnt1, 1);
|
||||
} else {
|
||||
clrldi(cnt1, cnt1, 32);
|
||||
}
|
||||
|
||||
if (ae != StrIntrinsicNode::LL) {
|
||||
srwi(cnt2, cnt2, 1);
|
||||
} else {
|
||||
clrldi(cnt2, cnt2, 32);
|
||||
}
|
||||
|
||||
// See if the lengths are different, and calculate min in cnt1.
|
||||
// Save diff in case we need it for a tie-breaker.
|
||||
subf_(diff, cnt2, cnt1); // diff = cnt1 - cnt2
|
||||
// if (diff > 0) { cnt1 = cnt2; }
|
||||
if (VM_Version::has_isel()) {
|
||||
isel(cnt1, CCR0, Assembler::greater, /*invert*/ false, cnt2);
|
||||
} else {
|
||||
Label Lskip;
|
||||
blt(CCR0, Lskip);
|
||||
mr(cnt1, cnt2);
|
||||
bind(Lskip);
|
||||
}
|
||||
|
||||
// Rename registers
|
||||
Register chr1 = result;
|
||||
Register chr2 = tmp0;
|
||||
|
||||
// Compare multiple characters in fast loop (only implemented for same encoding).
|
||||
int stride1 = 8, stride2 = 8;
|
||||
if (ae == StrIntrinsicNode::LL || ae == StrIntrinsicNode::UU) {
|
||||
int log2_chars_per_iter = (ae == StrIntrinsicNode::LL) ? 3 : 2;
|
||||
Label Lfastloop, Lskipfast;
|
||||
|
||||
srwi_(tmp0, cnt1, log2_chars_per_iter);
|
||||
beq(CCR0, Lskipfast);
|
||||
rldicl(cnt2, cnt1, 0, 64 - log2_chars_per_iter); // Remaining characters.
|
||||
li(cnt1, 1 << log2_chars_per_iter); // Initialize for failure case: Rescan characters from current iteration.
|
||||
mtctr(tmp0);
|
||||
|
||||
bind(Lfastloop);
|
||||
ld(chr1, 0, str1);
|
||||
ld(chr2, 0, str2);
|
||||
cmpd(CCR0, chr1, chr2);
|
||||
bne(CCR0, Lslow);
|
||||
addi(str1, str1, stride1);
|
||||
addi(str2, str2, stride2);
|
||||
bdnz(Lfastloop);
|
||||
mr(cnt1, cnt2); // Remaining characters.
|
||||
bind(Lskipfast);
|
||||
}
|
||||
|
||||
// Loop which searches the first difference character by character.
|
||||
cmpwi(CCR0, cnt1, 0);
|
||||
beq(CCR0, Lreturn_diff);
|
||||
bind(Lslow);
|
||||
mtctr(cnt1);
|
||||
|
||||
switch (ae) {
|
||||
case StrIntrinsicNode::LL: stride1 = 1; stride2 = 1; break;
|
||||
case StrIntrinsicNode::UL: // fallthru (see comment above)
|
||||
case StrIntrinsicNode::LU: stride1 = 1; stride2 = 2; break;
|
||||
case StrIntrinsicNode::UU: stride1 = 2; stride2 = 2; break;
|
||||
default: ShouldNotReachHere(); break;
|
||||
}
|
||||
|
||||
bind(Lloop);
|
||||
if (stride1 == 1) { lbz(chr1, 0, str1); } else { lhz(chr1, 0, str1); }
|
||||
if (stride2 == 1) { lbz(chr2, 0, str2); } else { lhz(chr2, 0, str2); }
|
||||
subf_(result, chr2, chr1); // result = chr1 - chr2
|
||||
bne(CCR0, Ldone);
|
||||
addi(str1, str1, stride1);
|
||||
addi(str2, str2, stride2);
|
||||
bdnz(Lloop);
|
||||
|
||||
// If strings are equal up to min length, return the length difference.
|
||||
bind(Lreturn_diff);
|
||||
mr(result, diff);
|
||||
|
||||
// Otherwise, return the difference between the first mismatched chars.
|
||||
bind(Ldone);
|
||||
if (ae == StrIntrinsicNode::UL) {
|
||||
neg(result, result); // Negate result (see note above).
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::array_equals(bool is_array_equ, Register ary1, Register ary2,
|
||||
Register limit, Register tmp1, Register result, bool is_byte) {
|
||||
const Register tmp0 = R0;
|
||||
assert_different_registers(ary1, ary2, limit, tmp0, tmp1, result);
|
||||
Label Ldone, Lskiploop, Lloop, Lfastloop, Lskipfast;
|
||||
bool limit_needs_shift = false;
|
||||
|
||||
if (is_array_equ) {
|
||||
const int length_offset = arrayOopDesc::length_offset_in_bytes();
|
||||
const int base_offset = arrayOopDesc::base_offset_in_bytes(is_byte ? T_BYTE : T_CHAR);
|
||||
|
||||
// Return true if the same array.
|
||||
cmpd(CCR0, ary1, ary2);
|
||||
beq(CCR0, Lskiploop);
|
||||
|
||||
// Return false if one of them is NULL.
|
||||
cmpdi(CCR0, ary1, 0);
|
||||
cmpdi(CCR1, ary2, 0);
|
||||
li(result, 0);
|
||||
cror(CCR0, Assembler::equal, CCR1, Assembler::equal);
|
||||
beq(CCR0, Ldone);
|
||||
|
||||
// Load the lengths of arrays.
|
||||
lwz(limit, length_offset, ary1);
|
||||
lwz(tmp0, length_offset, ary2);
|
||||
|
||||
// Return false if the two arrays are not equal length.
|
||||
cmpw(CCR0, limit, tmp0);
|
||||
bne(CCR0, Ldone);
|
||||
|
||||
// Load array addresses.
|
||||
addi(ary1, ary1, base_offset);
|
||||
addi(ary2, ary2, base_offset);
|
||||
} else {
|
||||
limit_needs_shift = !is_byte;
|
||||
li(result, 0); // Assume not equal.
|
||||
}
|
||||
|
||||
// Rename registers
|
||||
Register chr1 = tmp0;
|
||||
Register chr2 = tmp1;
|
||||
|
||||
// Compare 8 bytes per iteration in fast loop.
|
||||
const int log2_chars_per_iter = is_byte ? 3 : 2;
|
||||
|
||||
srwi_(tmp0, limit, log2_chars_per_iter + (limit_needs_shift ? 1 : 0));
|
||||
beq(CCR0, Lskipfast);
|
||||
mtctr(tmp0);
|
||||
|
||||
bind(Lfastloop);
|
||||
ld(chr1, 0, ary1);
|
||||
ld(chr2, 0, ary2);
|
||||
addi(ary1, ary1, 8);
|
||||
addi(ary2, ary2, 8);
|
||||
cmpd(CCR0, chr1, chr2);
|
||||
bne(CCR0, Ldone);
|
||||
bdnz(Lfastloop);
|
||||
|
||||
bind(Lskipfast);
|
||||
rldicl_(limit, limit, limit_needs_shift ? 64 - 1 : 0, 64 - log2_chars_per_iter); // Remaining characters.
|
||||
beq(CCR0, Lskiploop);
|
||||
mtctr(limit);
|
||||
|
||||
// Character by character.
|
||||
bind(Lloop);
|
||||
if (is_byte) {
|
||||
lbz(chr1, 0, ary1);
|
||||
lbz(chr2, 0, ary2);
|
||||
addi(ary1, ary1, 1);
|
||||
addi(ary2, ary2, 1);
|
||||
} else {
|
||||
lhz(chr1, 0, ary1);
|
||||
lhz(chr2, 0, ary2);
|
||||
addi(ary1, ary1, 2);
|
||||
addi(ary2, ary2, 2);
|
||||
}
|
||||
cmpw(CCR0, chr1, chr2);
|
||||
bne(CCR0, Ldone);
|
||||
bdnz(Lloop);
|
||||
|
||||
bind(Lskiploop);
|
||||
li(result, 1); // All characters are equal.
|
||||
bind(Ldone);
|
||||
}
|
||||
|
||||
void MacroAssembler::string_indexof(Register result, Register haystack, Register haycnt,
|
||||
Register needle, ciTypeArray* needle_values, Register needlecnt, int needlecntval,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4, int ae) {
|
||||
|
||||
// Ensure 0<needlecnt<=haycnt in ideal graph as prerequisite!
|
||||
Label L_TooShort, L_Found, L_NotFound, L_End;
|
||||
Register last_addr = haycnt, // Kill haycnt at the beginning.
|
||||
addr = tmp1,
|
||||
n_start = tmp2,
|
||||
ch1 = tmp3,
|
||||
ch2 = R0;
|
||||
|
||||
assert(ae != StrIntrinsicNode::LU, "Invalid encoding");
|
||||
const int h_csize = (ae == StrIntrinsicNode::LL) ? 1 : 2;
|
||||
const int n_csize = (ae == StrIntrinsicNode::UU) ? 2 : 1;
|
||||
|
||||
// **************************************************************************************************
|
||||
// Prepare for main loop: optimized for needle count >=2, bail out otherwise.
|
||||
// **************************************************************************************************
|
||||
|
||||
// Compute last haystack addr to use if no match gets found.
|
||||
clrldi(haycnt, haycnt, 32); // Ensure positive int is valid as 64 bit value.
|
||||
addi(addr, haystack, -h_csize); // Accesses use pre-increment.
|
||||
if (needlecntval == 0) { // variable needlecnt
|
||||
cmpwi(CCR6, needlecnt, 2);
|
||||
clrldi(needlecnt, needlecnt, 32); // Ensure positive int is valid as 64 bit value.
|
||||
blt(CCR6, L_TooShort); // Variable needlecnt: handle short needle separately.
|
||||
}
|
||||
|
||||
if (n_csize == 2) { lwz(n_start, 0, needle); } else { lhz(n_start, 0, needle); } // Load first 2 characters of needle.
|
||||
|
||||
if (needlecntval == 0) { // variable needlecnt
|
||||
subf(ch1, needlecnt, haycnt); // Last character index to compare is haycnt-needlecnt.
|
||||
addi(needlecnt, needlecnt, -2); // Rest of needle.
|
||||
} else { // constant needlecnt
|
||||
guarantee(needlecntval != 1, "IndexOf with single-character needle must be handled separately");
|
||||
assert((needlecntval & 0x7fff) == needlecntval, "wrong immediate");
|
||||
addi(ch1, haycnt, -needlecntval); // Last character index to compare is haycnt-needlecnt.
|
||||
if (needlecntval > 3) { li(needlecnt, needlecntval - 2); } // Rest of needle.
|
||||
}
|
||||
|
||||
if (h_csize == 2) { slwi(ch1, ch1, 1); } // Scale to number of bytes.
|
||||
|
||||
if (ae ==StrIntrinsicNode::UL) {
|
||||
srwi(tmp4, n_start, 1*8); // ___0
|
||||
rlwimi(n_start, tmp4, 2*8, 0, 23); // _0_1
|
||||
}
|
||||
|
||||
add(last_addr, haystack, ch1); // Point to last address to compare (haystack+2*(haycnt-needlecnt)).
|
||||
|
||||
// Main Loop (now we have at least 2 characters).
|
||||
Label L_OuterLoop, L_InnerLoop, L_FinalCheck, L_Comp1, L_Comp2;
|
||||
bind(L_OuterLoop); // Search for 1st 2 characters.
|
||||
Register addr_diff = tmp4;
|
||||
subf(addr_diff, addr, last_addr); // Difference between already checked address and last address to check.
|
||||
addi(addr, addr, h_csize); // This is the new address we want to use for comparing.
|
||||
srdi_(ch2, addr_diff, h_csize);
|
||||
beq(CCR0, L_FinalCheck); // 2 characters left?
|
||||
mtctr(ch2); // num of characters / 2
|
||||
bind(L_InnerLoop); // Main work horse (2x unrolled search loop)
|
||||
if (h_csize == 2) { // Load 2 characters of haystack (ignore alignment).
|
||||
lwz(ch1, 0, addr);
|
||||
lwz(ch2, 2, addr);
|
||||
} else {
|
||||
lhz(ch1, 0, addr);
|
||||
lhz(ch2, 1, addr);
|
||||
}
|
||||
cmpw(CCR0, ch1, n_start); // Compare 2 characters (1 would be sufficient but try to reduce branches to CompLoop).
|
||||
cmpw(CCR1, ch2, n_start);
|
||||
beq(CCR0, L_Comp1); // Did we find the needle start?
|
||||
beq(CCR1, L_Comp2);
|
||||
addi(addr, addr, 2 * h_csize);
|
||||
bdnz(L_InnerLoop);
|
||||
bind(L_FinalCheck);
|
||||
andi_(addr_diff, addr_diff, h_csize); // Remaining characters not covered by InnerLoop: (num of characters) & 1.
|
||||
beq(CCR0, L_NotFound);
|
||||
if (h_csize == 2) { lwz(ch1, 0, addr); } else { lhz(ch1, 0, addr); } // One position left at which we have to compare.
|
||||
cmpw(CCR1, ch1, n_start);
|
||||
beq(CCR1, L_Comp1);
|
||||
bind(L_NotFound);
|
||||
li(result, -1); // not found
|
||||
b(L_End);
|
||||
|
||||
// **************************************************************************************************
|
||||
// Special Case: unfortunately, the variable needle case can be called with needlecnt<2
|
||||
// **************************************************************************************************
|
||||
if (needlecntval == 0) { // We have to handle these cases separately.
|
||||
Label L_OneCharLoop;
|
||||
bind(L_TooShort);
|
||||
mtctr(haycnt);
|
||||
if (n_csize == 2) { lhz(n_start, 0, needle); } else { lbz(n_start, 0, needle); } // First character of needle
|
||||
bind(L_OneCharLoop);
|
||||
if (h_csize == 2) { lhzu(ch1, 2, addr); } else { lbzu(ch1, 1, addr); }
|
||||
cmpw(CCR1, ch1, n_start);
|
||||
beq(CCR1, L_Found); // Did we find the one character needle?
|
||||
bdnz(L_OneCharLoop);
|
||||
li(result, -1); // Not found.
|
||||
b(L_End);
|
||||
}
|
||||
|
||||
// **************************************************************************************************
|
||||
// Regular Case Part II: compare rest of needle (first 2 characters have been compared already)
|
||||
// **************************************************************************************************
|
||||
|
||||
// Compare the rest
|
||||
bind(L_Comp2);
|
||||
addi(addr, addr, h_csize); // First comparison has failed, 2nd one hit.
|
||||
bind(L_Comp1); // Addr points to possible needle start.
|
||||
if (needlecntval != 2) { // Const needlecnt==2?
|
||||
if (needlecntval != 3) {
|
||||
if (needlecntval == 0) { beq(CCR6, L_Found); } // Variable needlecnt==2?
|
||||
Register n_ind = tmp4,
|
||||
h_ind = n_ind;
|
||||
li(n_ind, 2 * n_csize); // First 2 characters are already compared, use index 2.
|
||||
mtctr(needlecnt); // Decremented by 2, still > 0.
|
||||
Label L_CompLoop;
|
||||
bind(L_CompLoop);
|
||||
if (ae ==StrIntrinsicNode::UL) {
|
||||
h_ind = ch1;
|
||||
sldi(h_ind, n_ind, 1);
|
||||
}
|
||||
if (n_csize == 2) { lhzx(ch2, needle, n_ind); } else { lbzx(ch2, needle, n_ind); }
|
||||
if (h_csize == 2) { lhzx(ch1, addr, h_ind); } else { lbzx(ch1, addr, h_ind); }
|
||||
cmpw(CCR1, ch1, ch2);
|
||||
bne(CCR1, L_OuterLoop);
|
||||
addi(n_ind, n_ind, n_csize);
|
||||
bdnz(L_CompLoop);
|
||||
} else { // No loop required if there's only one needle character left.
|
||||
if (n_csize == 2) { lhz(ch2, 2 * 2, needle); } else { lbz(ch2, 2 * 1, needle); }
|
||||
if (h_csize == 2) { lhz(ch1, 2 * 2, addr); } else { lbz(ch1, 2 * 1, addr); }
|
||||
cmpw(CCR1, ch1, ch2);
|
||||
bne(CCR1, L_OuterLoop);
|
||||
}
|
||||
}
|
||||
// Return index ...
|
||||
bind(L_Found);
|
||||
subf(result, haystack, addr); // relative to haystack, ...
|
||||
if (h_csize == 2) { srdi(result, result, 1); } // in characters.
|
||||
bind(L_End);
|
||||
} // string_indexof
|
||||
|
||||
void MacroAssembler::string_indexof_char(Register result, Register haystack, Register haycnt,
|
||||
Register needle, jchar needleChar, Register tmp1, Register tmp2, bool is_byte) {
|
||||
assert_different_registers(haystack, haycnt, needle, tmp1, tmp2);
|
||||
|
||||
Label L_InnerLoop, L_FinalCheck, L_Found1, L_Found2, L_NotFound, L_End;
|
||||
Register addr = tmp1,
|
||||
ch1 = tmp2,
|
||||
ch2 = R0;
|
||||
|
||||
const int h_csize = is_byte ? 1 : 2;
|
||||
|
||||
//4:
|
||||
srwi_(tmp2, haycnt, 1); // Shift right by exact_log2(UNROLL_FACTOR).
|
||||
mr(addr, haystack);
|
||||
beq(CCR0, L_FinalCheck);
|
||||
mtctr(tmp2); // Move to count register.
|
||||
//8:
|
||||
bind(L_InnerLoop); // Main work horse (2x unrolled search loop).
|
||||
if (!is_byte) {
|
||||
lhz(ch1, 0, addr);
|
||||
lhz(ch2, 2, addr);
|
||||
} else {
|
||||
lbz(ch1, 0, addr);
|
||||
lbz(ch2, 1, addr);
|
||||
}
|
||||
(needle != R0) ? cmpw(CCR0, ch1, needle) : cmplwi(CCR0, ch1, (unsigned int)needleChar);
|
||||
(needle != R0) ? cmpw(CCR1, ch2, needle) : cmplwi(CCR1, ch2, (unsigned int)needleChar);
|
||||
beq(CCR0, L_Found1); // Did we find the needle?
|
||||
beq(CCR1, L_Found2);
|
||||
addi(addr, addr, 2 * h_csize);
|
||||
bdnz(L_InnerLoop);
|
||||
//16:
|
||||
bind(L_FinalCheck);
|
||||
andi_(R0, haycnt, 1);
|
||||
beq(CCR0, L_NotFound);
|
||||
if (!is_byte) { lhz(ch1, 0, addr); } else { lbz(ch1, 0, addr); } // One position left at which we have to compare.
|
||||
(needle != R0) ? cmpw(CCR1, ch1, needle) : cmplwi(CCR1, ch1, (unsigned int)needleChar);
|
||||
beq(CCR1, L_Found1);
|
||||
//21:
|
||||
bind(L_NotFound);
|
||||
li(result, -1); // Not found.
|
||||
b(L_End);
|
||||
|
||||
bind(L_Found2);
|
||||
addi(addr, addr, h_csize);
|
||||
//24:
|
||||
bind(L_Found1); // Return index ...
|
||||
subf(result, haystack, addr); // relative to haystack, ...
|
||||
if (!is_byte) { srdi(result, result, 1); } // in characters.
|
||||
bind(L_End);
|
||||
} // string_indexof_char
|
||||
|
||||
|
||||
void MacroAssembler::has_negatives(Register src, Register cnt, Register result,
|
||||
Register tmp1, Register tmp2) {
|
||||
const Register tmp0 = R0;
|
||||
assert_different_registers(src, result, cnt, tmp0, tmp1, tmp2);
|
||||
Label Lfastloop, Lslow, Lloop, Lnoneg, Ldone;
|
||||
|
||||
// Check if cnt >= 8 (= 16 bytes)
|
||||
lis(tmp1, (int)(short)0x8080); // tmp1 = 0x8080808080808080
|
||||
srwi_(tmp2, cnt, 4);
|
||||
li(result, 1); // Assume there's a negative byte.
|
||||
beq(CCR0, Lslow);
|
||||
ori(tmp1, tmp1, 0x8080);
|
||||
rldimi(tmp1, tmp1, 32, 0);
|
||||
mtctr(tmp2);
|
||||
|
||||
// 2x unrolled loop
|
||||
bind(Lfastloop);
|
||||
ld(tmp2, 0, src);
|
||||
ld(tmp0, 8, src);
|
||||
|
||||
orr(tmp0, tmp2, tmp0);
|
||||
|
||||
and_(tmp0, tmp0, tmp1);
|
||||
bne(CCR0, Ldone); // Found negative byte.
|
||||
addi(src, src, 16);
|
||||
|
||||
bdnz(Lfastloop);
|
||||
|
||||
bind(Lslow); // Fallback to slow version
|
||||
rldicl_(tmp0, cnt, 0, 64-4);
|
||||
beq(CCR0, Lnoneg);
|
||||
mtctr(tmp0);
|
||||
bind(Lloop);
|
||||
lbz(tmp0, 0, src);
|
||||
addi(src, src, 1);
|
||||
andi_(tmp0, tmp0, 0x80);
|
||||
bne(CCR0, Ldone); // Found negative byte.
|
||||
bdnz(Lloop);
|
||||
bind(Lnoneg);
|
||||
li(result, 0);
|
||||
|
||||
bind(Ldone);
|
||||
}
|
||||
|
||||
#endif // Compiler2
|
||||
|
||||
// Helpers for Intrinsic Emitters
|
||||
//
|
||||
// Revert the byte order of a 32bit value in a register
|
||||
|
@ -761,39 +761,6 @@ class MacroAssembler: public Assembler {
|
||||
void clear_memory_constlen(Register base_ptr, int cnt_dwords, Register tmp = R0);
|
||||
void clear_memory_doubleword(Register base_ptr, Register cnt_dwords, Register tmp = R0, long const_cnt = -1);
|
||||
|
||||
#ifdef COMPILER2
|
||||
// Intrinsics for CompactStrings
|
||||
// Compress char[] to byte[] by compressing 16 bytes at once.
|
||||
void string_compress_16(Register src, Register dst, Register cnt,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5,
|
||||
Label& Lfailure);
|
||||
|
||||
// Compress char[] to byte[]. cnt must be positive int.
|
||||
void string_compress(Register src, Register dst, Register cnt, Register tmp, Label& Lfailure);
|
||||
|
||||
// Inflate byte[] to char[] by inflating 16 bytes at once.
|
||||
void string_inflate_16(Register src, Register dst, Register cnt,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4, Register tmp5);
|
||||
|
||||
// Inflate byte[] to char[]. cnt must be positive int.
|
||||
void string_inflate(Register src, Register dst, Register cnt, Register tmp);
|
||||
|
||||
void string_compare(Register str1, Register str2, Register cnt1, Register cnt2,
|
||||
Register tmp1, Register result, int ae);
|
||||
|
||||
void array_equals(bool is_array_equ, Register ary1, Register ary2,
|
||||
Register limit, Register tmp1, Register result, bool is_byte);
|
||||
|
||||
void string_indexof(Register result, Register haystack, Register haycnt,
|
||||
Register needle, ciTypeArray* needle_values, Register needlecnt, int needlecntval,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4, int ae);
|
||||
|
||||
void string_indexof_char(Register result, Register haystack, Register haycnt,
|
||||
Register needle, jchar needleChar, Register tmp1, Register tmp2, bool is_byte);
|
||||
|
||||
void has_negatives(Register src, Register cnt, Register result, Register tmp1, Register tmp2);
|
||||
#endif
|
||||
|
||||
// Emitters for BigInteger.multiplyToLen intrinsic.
|
||||
inline void multiply64(Register dest_hi, Register dest_lo,
|
||||
Register x, Register y);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2015 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -267,7 +267,7 @@ inline address MacroAssembler::last_calls_return_pc() {
|
||||
|
||||
// Read from the polling page, its address is already in a register.
|
||||
inline void MacroAssembler::load_from_polling_page(Register polling_page_address, int offset) {
|
||||
if (SafepointMechanism::uses_thread_local_poll() && USE_POLL_BIT_ONLY) {
|
||||
if (USE_POLL_BIT_ONLY) {
|
||||
int encoding = SafepointMechanism::poll_bit();
|
||||
tdi(traptoGreaterThanUnsigned | traptoEqual, polling_page_address, encoding);
|
||||
} else {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -92,7 +92,7 @@ class NativeInstruction {
|
||||
bool is_safepoint_poll() {
|
||||
// Is the current instruction a POTENTIAL read access to the polling page?
|
||||
// The current arguments of the instruction are not checked!
|
||||
if (SafepointMechanism::uses_thread_local_poll() && USE_POLL_BIT_ONLY) {
|
||||
if (USE_POLL_BIT_ONLY) {
|
||||
int encoding = SafepointMechanism::poll_bit();
|
||||
return MacroAssembler::is_tdi(long_at(0), Assembler::traptoGreaterThanUnsigned | Assembler::traptoEqual,
|
||||
-1, encoding);
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2012, 2019 SAP SE. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
@ -982,10 +982,26 @@ source_hpp %{
|
||||
|
||||
source %{
|
||||
|
||||
void PhaseOutput::pd_perform_mach_node_analysis() {
|
||||
}
|
||||
|
||||
int MachNode::pd_alignment_required() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int MachNode::compute_padding(int current_offset) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Should the matcher clone input 'm' of node 'n'?
|
||||
bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Should the Matcher clone shifts on addressing modes, expecting them
|
||||
// to be subsumed into complex addressing expressions or compute them
|
||||
// into registers?
|
||||
bool Matcher::clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
|
||||
bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
|
||||
return clone_base_plus_offset_address(m, mstack, address_visited);
|
||||
}
|
||||
|
||||
@ -1144,7 +1160,7 @@ bool SafePointNode::needs_polling_address_input() {
|
||||
|
||||
// Emit an interrupt that is caught by the debugger (for debugging compiler).
|
||||
void emit_break(CodeBuffer &cbuf) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ illtrap();
|
||||
}
|
||||
|
||||
@ -1165,7 +1181,7 @@ uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
|
||||
//=============================================================================
|
||||
|
||||
void emit_nop(CodeBuffer &cbuf) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ nop();
|
||||
}
|
||||
|
||||
@ -1184,12 +1200,14 @@ source_hpp %{ // Header information of the source block.
|
||||
//---< Used for optimization in Compile::Shorten_branches >---
|
||||
//--------------------------------------------------------------
|
||||
|
||||
class C2_MacroAssembler;
|
||||
|
||||
class CallStubImpl {
|
||||
|
||||
public:
|
||||
|
||||
// Emit call stub, compiled java to interpreter.
|
||||
static void emit_trampoline_stub(MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset);
|
||||
static void emit_trampoline_stub(C2_MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset);
|
||||
|
||||
// Size of call trampoline stub.
|
||||
// This doesn't need to be accurate to the byte, but it
|
||||
@ -1220,7 +1238,7 @@ source %{
|
||||
// load the call target from the constant pool
|
||||
// branch via CTR (LR/link still points to the call-site above)
|
||||
|
||||
void CallStubImpl::emit_trampoline_stub(MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset) {
|
||||
void CallStubImpl::emit_trampoline_stub(C2_MacroAssembler &_masm, int destination_toc_offset, int insts_call_instruction_offset) {
|
||||
address stub = __ emit_trampoline_stub(destination_toc_offset, insts_call_instruction_offset);
|
||||
if (stub == NULL) {
|
||||
ciEnv::current()->record_out_of_memory_failure();
|
||||
@ -1251,7 +1269,7 @@ typedef struct {
|
||||
// - Add a relocation at the branch-and-link instruction.
|
||||
// - Emit a branch-and-link.
|
||||
// - Remember the return pc offset.
|
||||
EmitCallOffsets emit_call_with_trampoline_stub(MacroAssembler &_masm, address entry_point, relocInfo::relocType rtype) {
|
||||
EmitCallOffsets emit_call_with_trampoline_stub(C2_MacroAssembler &_masm, address entry_point, relocInfo::relocType rtype) {
|
||||
EmitCallOffsets offsets = { -1, -1 };
|
||||
const int start_offset = __ offset();
|
||||
offsets.insts_call_instruction_offset = __ offset();
|
||||
@ -1379,7 +1397,7 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
|
||||
|
||||
void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
Compile* C = ra_->C;
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
const long framesize = C->output()->frame_size_in_bytes();
|
||||
assert(framesize % (2 * wordSize) == 0, "must preserve 2*wordSize alignment");
|
||||
@ -1571,7 +1589,7 @@ void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
|
||||
|
||||
void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
Compile* C = ra_->C;
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
const long framesize = ((long)C->output()->frame_slots()) << LogBytesPerInt;
|
||||
assert(framesize >= 0, "negative frame-size?");
|
||||
@ -1587,11 +1605,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
}
|
||||
|
||||
if (method_needs_polling) {
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
__ ld(polling_page, in_bytes(JavaThread::polling_page_offset()), R16_thread);
|
||||
} else {
|
||||
__ load_const_optimized(polling_page, (long)(address) os::get_polling_page());
|
||||
}
|
||||
__ ld(polling_page, in_bytes(JavaThread::polling_page_offset()), R16_thread);
|
||||
}
|
||||
|
||||
if (!method_is_frameless) {
|
||||
@ -1627,17 +1641,9 @@ const Pipeline * MachEpilogNode::pipeline() const {
|
||||
return MachNode::pipeline_class();
|
||||
}
|
||||
|
||||
// This method seems to be obsolete. It is declared in machnode.hpp
|
||||
// and defined in all *.ad files, but it is never called. Should we
|
||||
// get rid of it?
|
||||
int MachEpilogNode::safepoint_offset() const {
|
||||
assert(do_polling(), "no return for this epilog node");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0 // TODO: PPC port
|
||||
void MachLoadPollAddrLateNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
if (LoadPollAddressFromThread) {
|
||||
_masm.ld(R11, in_bytes(JavaThread::poll_address_offset()), R16_thread);
|
||||
} else {
|
||||
@ -1754,7 +1760,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
|
||||
int src_offset = ra_->reg2offset(src_lo);
|
||||
int dst_offset = ra_->reg2offset(dst_lo);
|
||||
if (cbuf) {
|
||||
MacroAssembler _masm(cbuf);
|
||||
C2_MacroAssembler _masm(cbuf);
|
||||
__ ld(R0, src_offset, R1_SP);
|
||||
__ std(R0, dst_offset, R1_SP);
|
||||
__ ld(R0, src_offset+8, R1_SP);
|
||||
@ -1767,7 +1773,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
|
||||
VectorSRegister Rsrc = as_VectorSRegister(Matcher::_regEncode[src_lo]);
|
||||
int dst_offset = ra_->reg2offset(dst_lo);
|
||||
if (cbuf) {
|
||||
MacroAssembler _masm(cbuf);
|
||||
C2_MacroAssembler _masm(cbuf);
|
||||
__ addi(R0, R1_SP, dst_offset);
|
||||
__ stxvd2x(Rsrc, R0);
|
||||
}
|
||||
@ -1778,7 +1784,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
|
||||
VectorSRegister Rdst = as_VectorSRegister(Matcher::_regEncode[dst_lo]);
|
||||
int src_offset = ra_->reg2offset(src_lo);
|
||||
if (cbuf) {
|
||||
MacroAssembler _masm(cbuf);
|
||||
C2_MacroAssembler _masm(cbuf);
|
||||
__ addi(R0, R1_SP, src_offset);
|
||||
__ lxvd2x(Rdst, R0);
|
||||
}
|
||||
@ -1789,7 +1795,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
|
||||
VectorSRegister Rsrc = as_VectorSRegister(Matcher::_regEncode[src_lo]);
|
||||
VectorSRegister Rdst = as_VectorSRegister(Matcher::_regEncode[dst_lo]);
|
||||
if (cbuf) {
|
||||
MacroAssembler _masm(cbuf);
|
||||
C2_MacroAssembler _masm(cbuf);
|
||||
__ xxlor(Rdst, Rsrc, Rsrc);
|
||||
}
|
||||
size += 4;
|
||||
@ -1833,7 +1839,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
|
||||
size = (Rsrc != Rdst) ? 4 : 0;
|
||||
|
||||
if (cbuf) {
|
||||
MacroAssembler _masm(cbuf);
|
||||
C2_MacroAssembler _masm(cbuf);
|
||||
if (size) {
|
||||
__ mr(Rdst, Rsrc);
|
||||
}
|
||||
@ -1879,7 +1885,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
|
||||
// Check for float reg-reg copy.
|
||||
if (src_lo_rc == rc_float && dst_lo_rc == rc_float) {
|
||||
if (cbuf) {
|
||||
MacroAssembler _masm(cbuf);
|
||||
C2_MacroAssembler _masm(cbuf);
|
||||
FloatRegister Rsrc = as_FloatRegister(Matcher::_regEncode[src_lo]);
|
||||
FloatRegister Rdst = as_FloatRegister(Matcher::_regEncode[dst_lo]);
|
||||
__ fmr(Rdst, Rsrc);
|
||||
@ -2049,7 +2055,7 @@ void MachNopNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
|
||||
#endif
|
||||
|
||||
void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
// _count contains the number of nops needed for padding.
|
||||
for (int i = 0; i < _count; i++) {
|
||||
__ nop();
|
||||
@ -2070,7 +2076,7 @@ void BoxLockNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
|
||||
#endif
|
||||
|
||||
void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
|
||||
int reg = ra_->get_encode(this);
|
||||
@ -2096,7 +2102,7 @@ void MachUEPNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
|
||||
|
||||
void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
// This is the unverified entry point.
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
// Inline_cache contains a klass.
|
||||
Register ic_klass = as_Register(Matcher::inline_cache_reg_encode());
|
||||
@ -2174,12 +2180,19 @@ class HandlerImpl {
|
||||
|
||||
};
|
||||
|
||||
class Node::PD {
|
||||
public:
|
||||
enum NodeFlags {
|
||||
_last_flag = Node::_last_flag
|
||||
};
|
||||
};
|
||||
|
||||
%} // end source_hpp
|
||||
|
||||
source %{
|
||||
|
||||
int HandlerImpl::emit_exception_handler(CodeBuffer &cbuf) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
address base = __ start_a_stub(size_exception_handler());
|
||||
if (base == NULL) return 0; // CodeBuffer::expand failed
|
||||
@ -2196,7 +2209,7 @@ int HandlerImpl::emit_exception_handler(CodeBuffer &cbuf) {
|
||||
// The deopt_handler is like the exception handler, but it calls to
|
||||
// the deoptimization blob instead of jumping to the exception blob.
|
||||
int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
address base = __ start_a_stub(size_deopt_handler());
|
||||
if (base == NULL) return 0; // CodeBuffer::expand failed
|
||||
@ -2660,14 +2673,14 @@ const bool Matcher::convi2l_type_required = true;
|
||||
encode %{
|
||||
enc_class enc_unimplemented %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_compound);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ unimplemented("Unimplemented mach node encoding in AD file.", 13);
|
||||
%}
|
||||
|
||||
enc_class enc_untested %{
|
||||
#ifdef ASSERT
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_compound);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ untested("Untested mach node encoding in AD file.");
|
||||
#else
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_none);
|
||||
@ -2676,7 +2689,7 @@ encode %{
|
||||
|
||||
enc_class enc_lbz(iRegIdst dst, memory mem) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_lbz);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_);
|
||||
__ lbz($dst$$Register, Idisp, $mem$$base$$Register);
|
||||
%}
|
||||
@ -2684,7 +2697,7 @@ encode %{
|
||||
// Load acquire.
|
||||
enc_class enc_lbz_ac(iRegIdst dst, memory mem) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_compound);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_);
|
||||
__ lbz($dst$$Register, Idisp, $mem$$base$$Register);
|
||||
__ twi_0($dst$$Register);
|
||||
@ -2694,7 +2707,7 @@ encode %{
|
||||
enc_class enc_lhz(iRegIdst dst, memory mem) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_lhz);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_);
|
||||
__ lhz($dst$$Register, Idisp, $mem$$base$$Register);
|
||||
%}
|
||||
@ -2703,7 +2716,7 @@ encode %{
|
||||
enc_class enc_lhz_ac(iRegIdst dst, memory mem) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_compound);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_);
|
||||
__ lhz($dst$$Register, Idisp, $mem$$base$$Register);
|
||||
__ twi_0($dst$$Register);
|
||||
@ -2713,7 +2726,7 @@ encode %{
|
||||
enc_class enc_lwz(iRegIdst dst, memory mem) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_lwz);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_);
|
||||
__ lwz($dst$$Register, Idisp, $mem$$base$$Register);
|
||||
%}
|
||||
@ -2722,7 +2735,7 @@ encode %{
|
||||
enc_class enc_lwz_ac(iRegIdst dst, memory mem) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_compound);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_);
|
||||
__ lwz($dst$$Register, Idisp, $mem$$base$$Register);
|
||||
__ twi_0($dst$$Register);
|
||||
@ -2731,7 +2744,7 @@ encode %{
|
||||
|
||||
enc_class enc_ld(iRegLdst dst, memoryAlg4 mem) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_ld);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_);
|
||||
// Operand 'ds' requires 4-alignment.
|
||||
assert((Idisp & 0x3) == 0, "unaligned offset");
|
||||
@ -2741,7 +2754,7 @@ encode %{
|
||||
// Load acquire.
|
||||
enc_class enc_ld_ac(iRegLdst dst, memoryAlg4 mem) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_compound);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_);
|
||||
// Operand 'ds' requires 4-alignment.
|
||||
assert((Idisp & 0x3) == 0, "unaligned offset");
|
||||
@ -2752,7 +2765,7 @@ encode %{
|
||||
|
||||
enc_class enc_lfd(RegF dst, memory mem) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_lfd);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_);
|
||||
__ lfd($dst$$FloatRegister, Idisp, $mem$$base$$Register);
|
||||
%}
|
||||
@ -2760,7 +2773,7 @@ encode %{
|
||||
enc_class enc_load_long_constL(iRegLdst dst, immL src, iRegLdst toc) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_ld);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int toc_offset = 0;
|
||||
|
||||
address const_toc_addr;
|
||||
@ -2784,7 +2797,7 @@ encode %{
|
||||
enc_class enc_load_long_constL_hi(iRegLdst dst, iRegLdst toc, immL src) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_addis);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
if (!ra_->C->output()->in_scratch_emit_size()) {
|
||||
address const_toc_addr;
|
||||
@ -3019,7 +3032,7 @@ encode %{
|
||||
enc_class enc_load_long_constP(iRegLdst dst, immP src, iRegLdst toc) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_ld);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int toc_offset = 0;
|
||||
|
||||
intptr_t val = $src$$constant;
|
||||
@ -3052,7 +3065,7 @@ encode %{
|
||||
enc_class enc_load_long_constP_hi(iRegLdst dst, immP src, iRegLdst toc) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_addis);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
if (!ra_->C->output()->in_scratch_emit_size()) {
|
||||
intptr_t val = $src$$constant;
|
||||
relocInfo::relocType constant_reloc = $src->constant_reloc(); // src
|
||||
@ -3186,14 +3199,14 @@ encode %{
|
||||
|
||||
enc_class enc_stw(iRegIsrc src, memory mem) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_stw);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_);
|
||||
__ stw($src$$Register, Idisp, $mem$$base$$Register);
|
||||
%}
|
||||
|
||||
enc_class enc_std(iRegIsrc src, memoryAlg4 mem) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_std);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_);
|
||||
// Operand 'ds' requires 4-alignment.
|
||||
assert((Idisp & 0x3) == 0, "unaligned offset");
|
||||
@ -3202,14 +3215,14 @@ encode %{
|
||||
|
||||
enc_class enc_stfs(RegF src, memory mem) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_stfs);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_);
|
||||
__ stfs($src$$FloatRegister, Idisp, $mem$$base$$Register);
|
||||
%}
|
||||
|
||||
enc_class enc_stfd(RegF src, memory mem) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_stfd);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_);
|
||||
__ stfd($src$$FloatRegister, Idisp, $mem$$base$$Register);
|
||||
%}
|
||||
@ -3230,7 +3243,7 @@ encode %{
|
||||
// __ bind(skip_release);
|
||||
// __ stb(card mark);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label skip_storestore;
|
||||
|
||||
#if 0 // TODO: PPC port
|
||||
@ -3451,7 +3464,7 @@ encode %{
|
||||
enc_class enc_cmove_reg(iRegIdst dst, flagsRegSrc crx, iRegIsrc src, cmpOp cmp) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_cmove);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int cc = $cmp$$cmpcode;
|
||||
int flags_reg = $crx$$reg;
|
||||
Label done;
|
||||
@ -3466,7 +3479,7 @@ encode %{
|
||||
enc_class enc_cmove_imm(iRegIdst dst, flagsRegSrc crx, immI16 src, cmpOp cmp) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_cmove);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label done;
|
||||
assert((Assembler::bcondCRbiIs1 & ~Assembler::bcondCRbiIs0) == 8, "check encoding");
|
||||
// Branch if not (cmp crx).
|
||||
@ -3480,14 +3493,14 @@ encode %{
|
||||
// input mapping for latency computation.
|
||||
enc_class enc_andc(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_andc);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ andc($dst$$Register, $src1$$Register, $src2$$Register);
|
||||
%}
|
||||
|
||||
enc_class enc_convI2B_regI__cmove(iRegIdst dst, iRegIsrc src, flagsReg crx, immI16 zero, immI16 notzero) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_compound);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
Label done;
|
||||
__ cmpwi($crx$$CondRegister, $src$$Register, 0);
|
||||
@ -3500,7 +3513,7 @@ encode %{
|
||||
enc_class enc_convP2B_regP__cmove(iRegIdst dst, iRegPsrc src, flagsReg crx, immI16 zero, immI16 notzero) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_compound);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
Label done;
|
||||
__ cmpdi($crx$$CondRegister, $src$$Register, 0);
|
||||
@ -3513,7 +3526,7 @@ encode %{
|
||||
enc_class enc_cmove_bso_stackSlotL(iRegLdst dst, flagsRegSrc crx, stackSlotL mem ) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_cmove);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int Idisp = $mem$$disp + frame_slots_bias($mem$$base, ra_);
|
||||
Label done;
|
||||
__ bso($crx$$CondRegister, done);
|
||||
@ -3525,7 +3538,7 @@ encode %{
|
||||
enc_class enc_cmove_bso_reg(iRegLdst dst, flagsRegSrc crx, regD src) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_cmove);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label done;
|
||||
__ bso($crx$$CondRegister, done);
|
||||
__ mffprd($dst$$Register, $src$$FloatRegister);
|
||||
@ -3536,7 +3549,7 @@ encode %{
|
||||
enc_class enc_bc(flagsRegSrc crx, cmpOp cmp, Label lbl) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_bc);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label d; // dummy
|
||||
__ bind(d);
|
||||
Label* p = ($lbl$$label);
|
||||
@ -3566,7 +3579,7 @@ encode %{
|
||||
// to ppc64Opcode_bc in order to hide this detail from the scheduler.
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_bc);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label d; // dummy
|
||||
__ bind(d);
|
||||
Label* p = ($lbl$$label);
|
||||
@ -3598,7 +3611,7 @@ encode %{
|
||||
// to ppc64Opcode_bc in order to hide this detail from the scheduler.
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_bc);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label d; // dummy
|
||||
__ bind(d);
|
||||
Label* p = ($lbl$$label);
|
||||
@ -3683,7 +3696,7 @@ encode %{
|
||||
// Fake operand dst needed for PPC scheduler.
|
||||
assert($dst$$constant == 0x0, "dst must be 0x0");
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
// Mark the code position where the load from the safepoint
|
||||
// polling page was emitted as relocInfo::poll_type.
|
||||
__ relocate(relocInfo::poll_type);
|
||||
@ -3739,7 +3752,7 @@ encode %{
|
||||
enc_class enc_java_static_call(method meth) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_bl);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
address entry_point = (address)$meth$$method;
|
||||
|
||||
if (!_method) {
|
||||
@ -3789,7 +3802,7 @@ encode %{
|
||||
enc_class enc_java_dynamic_call_sched(method meth) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_bl);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
if (!ra_->C->output()->in_scratch_emit_size()) {
|
||||
// Create a call trampoline stub for the given method.
|
||||
@ -3892,7 +3905,7 @@ encode %{
|
||||
// In the code we have to use $constanttablebase.
|
||||
enc_class enc_java_dynamic_call(method meth, iRegLdst toc) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_compound);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int start_offset = __ offset();
|
||||
|
||||
Register Rtoc = (ra_) ? $constanttablebase : R2_TOC;
|
||||
@ -3951,7 +3964,7 @@ encode %{
|
||||
enc_class enc_java_to_runtime_call (method meth) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_compound);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
const address start_pc = __ pc();
|
||||
|
||||
#if defined(ABI_ELFv2)
|
||||
@ -3984,7 +3997,7 @@ encode %{
|
||||
// input mapping for latency computation.
|
||||
enc_class enc_leaf_call_mtctr(iRegLsrc src) %{
|
||||
// TODO: PPC port $archOpcode(ppc64Opcode_mtctr);
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ mtctr($src$$Register);
|
||||
%}
|
||||
|
||||
|
@ -3228,7 +3228,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
|
||||
// No exception case.
|
||||
__ BIND(noException);
|
||||
|
||||
if (SafepointMechanism::uses_thread_local_poll() && !cause_return) {
|
||||
if (!cause_return) {
|
||||
Label no_adjust;
|
||||
// If our stashed return pc was modified by the runtime we avoid touching it
|
||||
__ ld(R0, frame_size_in_bytes + _abi(lr), R1_SP);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2020, 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.
|
||||
*
|
||||
@ -2176,7 +2176,7 @@ void TemplateTable::_return(TosState state) {
|
||||
__ bind(Lskip_register_finalizer);
|
||||
}
|
||||
|
||||
if (SafepointMechanism::uses_thread_local_poll() && _desc->bytecode() != Bytecodes::_return_register_finalizer) {
|
||||
if (_desc->bytecode() != Bytecodes::_return_register_finalizer) {
|
||||
Label no_safepoint;
|
||||
__ ld(R11_scratch1, in_bytes(Thread::polling_page_offset()), R16_thread);
|
||||
__ andi_(R11_scratch1, R11_scratch1, SafepointMechanism::poll_bit());
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2019, SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -1214,12 +1214,7 @@ void LIR_Assembler::return_op(LIR_Opr result) {
|
||||
(result->is_single_fpu() && result->as_float_reg() == Z_F0) ||
|
||||
(result->is_double_fpu() && result->as_double_reg() == Z_F0), "convention");
|
||||
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
__ z_lg(Z_R1_scratch, Address(Z_thread, Thread::polling_page_offset()));
|
||||
} else {
|
||||
AddressLiteral pp(os::get_polling_page());
|
||||
__ load_const_optimized(Z_R1_scratch, pp);
|
||||
}
|
||||
__ z_lg(Z_R1_scratch, Address(Z_thread, Thread::polling_page_offset()));
|
||||
|
||||
// Pop the frame before the safepoint code.
|
||||
__ pop_frame_restore_retPC(initial_frame_size_in_bytes());
|
||||
@ -1238,12 +1233,7 @@ void LIR_Assembler::return_op(LIR_Opr result) {
|
||||
|
||||
int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) {
|
||||
const Register poll_addr = tmp->as_register_lo();
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
__ z_lg(poll_addr, Address(Z_thread, Thread::polling_page_offset()));
|
||||
} else {
|
||||
AddressLiteral pp(os::get_polling_page());
|
||||
__ load_const_optimized(poll_addr, pp);
|
||||
}
|
||||
__ z_lg(poll_addr, Address(Z_thread, Thread::polling_page_offset()));
|
||||
guarantee(info != NULL, "Shouldn't be NULL");
|
||||
add_debug_info_for_branch(info);
|
||||
int offset = __ offset();
|
||||
|
1281
src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp
Normal file
1281
src/hotspot/cpu/s390/c2_MacroAssembler_s390.cpp
Normal file
File diff suppressed because it is too large
Load Diff
76
src/hotspot/cpu/s390/c2_MacroAssembler_s390.hpp
Normal file
76
src/hotspot/cpu/s390/c2_MacroAssembler_s390.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CPU_S390_C2_MACROASSEMBLER_S390_HPP
|
||||
#define CPU_S390_C2_MACROASSEMBLER_S390_HPP
|
||||
|
||||
// C2_MacroAssembler contains high-level macros for C2
|
||||
|
||||
public:
|
||||
//-------------------------------------------
|
||||
// Special String Intrinsics Implementation.
|
||||
//-------------------------------------------
|
||||
// Intrinsics for CompactStrings
|
||||
// Restores: src, dst
|
||||
// Uses: cnt
|
||||
// Kills: tmp, Z_R0, Z_R1.
|
||||
// Early clobber: result.
|
||||
// Boolean precise controls accuracy of result value.
|
||||
unsigned int string_compress(Register result, Register src, Register dst, Register cnt,
|
||||
Register tmp, bool precise);
|
||||
|
||||
// Inflate byte[] to char[].
|
||||
unsigned int string_inflate_trot(Register src, Register dst, Register cnt, Register tmp);
|
||||
|
||||
// Inflate byte[] to char[].
|
||||
// Restores: src, dst
|
||||
// Uses: cnt
|
||||
// Kills: tmp, Z_R0, Z_R1.
|
||||
unsigned int string_inflate(Register src, Register dst, Register cnt, Register tmp);
|
||||
|
||||
// Inflate byte[] to char[], length known at compile time.
|
||||
// Restores: src, dst
|
||||
// Kills: tmp, Z_R0, Z_R1.
|
||||
// Note:
|
||||
// len is signed int. Counts # characters, not bytes.
|
||||
unsigned int string_inflate_const(Register src, Register dst, Register tmp, int len);
|
||||
|
||||
// Kills src.
|
||||
unsigned int has_negatives(Register result, Register src, Register cnt,
|
||||
Register odd_reg, Register even_reg, Register tmp);
|
||||
|
||||
unsigned int string_compare(Register str1, Register str2, Register cnt1, Register cnt2,
|
||||
Register odd_reg, Register even_reg, Register result, int ae);
|
||||
|
||||
unsigned int array_equals(bool is_array_equ, Register ary1, Register ary2, Register limit,
|
||||
Register odd_reg, Register even_reg, Register result, bool is_byte);
|
||||
|
||||
unsigned int string_indexof(Register result, Register haystack, Register haycnt,
|
||||
Register needle, Register needlecnt, int needlecntval,
|
||||
Register odd_reg, Register even_reg, int ae);
|
||||
|
||||
unsigned int string_indexof_char(Register result, Register haystack, Register haycnt,
|
||||
Register needle, jchar needleChar, Register odd_reg, Register even_reg, bool is_byte);
|
||||
|
||||
#endif // CPU_S390_C2_MACROASSEMBLER_S390_HPP
|
@ -66,7 +66,7 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
||||
}
|
||||
|
||||
// Unextended sp must be within the stack
|
||||
if (!thread->is_in_full_stack(unextended_sp)) {
|
||||
if (!thread->is_in_full_stack_checked(unextended_sp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -262,12 +262,12 @@ frame frame::sender(RegisterMap* map) const {
|
||||
}
|
||||
|
||||
void frame::patch_pc(Thread* thread, address pc) {
|
||||
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
|
||||
if (TracePcPatching) {
|
||||
tty->print_cr("patch_pc at address " PTR_FORMAT " [" PTR_FORMAT " -> " PTR_FORMAT "] ",
|
||||
p2i(&((address*) _sp)[-1]), p2i(((address*) _sp)[-1]), p2i(pc));
|
||||
}
|
||||
own_abi()->return_pc = (uint64_t)pc;
|
||||
_cb = CodeCache::find_blob(pc);
|
||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||
if (original_pc != NULL) {
|
||||
assert(original_pc == _pc, "expected original to be stored before patching");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, 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.
|
||||
*
|
||||
@ -56,6 +56,4 @@ const bool CCallingConventionRequiresIntsAsLongs = true;
|
||||
|
||||
#define SUPPORT_RESERVED_STACK_AREA
|
||||
|
||||
#define THREAD_LOCAL_POLL
|
||||
|
||||
#endif // CPU_S390_GLOBALDEFINITIONS_S390_HPP
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2019 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -116,7 +116,7 @@ void InterpreterMacroAssembler::dispatch_base(TosState state, address* table, bo
|
||||
// Dispatch table to use.
|
||||
load_absolute_address(Z_tmp_1, (address)table); // Z_tmp_1 = table;
|
||||
|
||||
if (SafepointMechanism::uses_thread_local_poll() && generate_poll) {
|
||||
if (generate_poll) {
|
||||
address *sfpt_tbl = Interpreter::safept_table(state);
|
||||
if (table != sfpt_tbl) {
|
||||
Label dispatch;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -841,52 +841,6 @@ class MacroAssembler: public Assembler {
|
||||
Register cnt_reg,
|
||||
Register tmp1_reg, Register tmp2_reg);
|
||||
|
||||
//-------------------------------------------
|
||||
// Special String Intrinsics Implementation.
|
||||
//-------------------------------------------
|
||||
// Intrinsics for CompactStrings
|
||||
// Restores: src, dst
|
||||
// Uses: cnt
|
||||
// Kills: tmp, Z_R0, Z_R1.
|
||||
// Early clobber: result.
|
||||
// Boolean precise controls accuracy of result value.
|
||||
#ifdef COMPILER2
|
||||
unsigned int string_compress(Register result, Register src, Register dst, Register cnt,
|
||||
Register tmp, bool precise);
|
||||
|
||||
// Inflate byte[] to char[].
|
||||
unsigned int string_inflate_trot(Register src, Register dst, Register cnt, Register tmp);
|
||||
|
||||
// Inflate byte[] to char[].
|
||||
// Restores: src, dst
|
||||
// Uses: cnt
|
||||
// Kills: tmp, Z_R0, Z_R1.
|
||||
unsigned int string_inflate(Register src, Register dst, Register cnt, Register tmp);
|
||||
|
||||
// Inflate byte[] to char[], length known at compile time.
|
||||
// Restores: src, dst
|
||||
// Kills: tmp, Z_R0, Z_R1.
|
||||
// Note:
|
||||
// len is signed int. Counts # characters, not bytes.
|
||||
unsigned int string_inflate_const(Register src, Register dst, Register tmp, int len);
|
||||
|
||||
// Kills src.
|
||||
unsigned int has_negatives(Register result, Register src, Register cnt,
|
||||
Register odd_reg, Register even_reg, Register tmp);
|
||||
|
||||
unsigned int string_compare(Register str1, Register str2, Register cnt1, Register cnt2,
|
||||
Register odd_reg, Register even_reg, Register result, int ae);
|
||||
|
||||
unsigned int array_equals(bool is_array_equ, Register ary1, Register ary2, Register limit,
|
||||
Register odd_reg, Register even_reg, Register result, bool is_byte);
|
||||
|
||||
unsigned int string_indexof(Register result, Register haystack, Register haycnt,
|
||||
Register needle, Register needlecnt, int needlecntval,
|
||||
Register odd_reg, Register even_reg, int ae);
|
||||
|
||||
unsigned int string_indexof_char(Register result, Register haystack, Register haycnt,
|
||||
Register needle, jchar needleChar, Register odd_reg, Register even_reg, bool is_byte);
|
||||
#endif
|
||||
|
||||
// Emit an oop const to the constant pool and set a relocation info
|
||||
// with address current_pc. Return the TOC offset of the constant.
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2017, 2019 SAP SE. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
@ -605,6 +605,17 @@ static Register reg_to_register_object(int register_encoding);
|
||||
// from the start of the call to the point where the return address
|
||||
// will point.
|
||||
|
||||
void PhaseOutput::pd_perform_mach_node_analysis() {
|
||||
}
|
||||
|
||||
int MachNode::pd_alignment_required() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int MachNode::compute_padding(int current_offset) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MachCallStaticJavaNode::ret_addr_offset() {
|
||||
if (_method) {
|
||||
return 8;
|
||||
@ -664,13 +675,13 @@ bool SafePointNode::needs_polling_address_input() {
|
||||
}
|
||||
|
||||
void emit_nop(CodeBuffer &cbuf) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ z_nop();
|
||||
}
|
||||
|
||||
// Emit an interrupt that is caught by the debugger (for debugging compiler).
|
||||
void emit_break(CodeBuffer &cbuf) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ z_illtrap();
|
||||
}
|
||||
|
||||
@ -735,7 +746,7 @@ static inline unsigned int z_emit_inst(CodeBuffer &cbuf, long value) {
|
||||
|
||||
// Check effective address (at runtime) for required alignment.
|
||||
static inline void z_assert_aligned(CodeBuffer &cbuf, int disp, Register index, Register base, int alignment) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
__ z_lay(Z_R0, disp, index, base);
|
||||
__ z_nill(Z_R0, alignment-1);
|
||||
@ -743,7 +754,7 @@ static inline void z_assert_aligned(CodeBuffer &cbuf, int disp, Register index,
|
||||
__ z_illtrap();
|
||||
}
|
||||
|
||||
int emit_call_reloc(MacroAssembler &_masm, intptr_t entry_point, relocInfo::relocType rtype,
|
||||
int emit_call_reloc(C2_MacroAssembler &_masm, intptr_t entry_point, relocInfo::relocType rtype,
|
||||
PhaseRegAlloc* ra_, bool is_native_call = false) {
|
||||
__ set_inst_mark(); // Used in z_enc_java_static_call() and emit_java_to_interp().
|
||||
address old_mark = __ inst_mark();
|
||||
@ -774,7 +785,7 @@ int emit_call_reloc(MacroAssembler &_masm, intptr_t entry_point, relocInfo::relo
|
||||
return (ret_off - start_off);
|
||||
}
|
||||
|
||||
static int emit_call_reloc(MacroAssembler &_masm, intptr_t entry_point, RelocationHolder const& rspec) {
|
||||
static int emit_call_reloc(C2_MacroAssembler &_masm, intptr_t entry_point, RelocationHolder const& rspec) {
|
||||
__ set_inst_mark(); // Used in z_enc_java_static_call() and emit_java_to_interp().
|
||||
address old_mark = __ inst_mark();
|
||||
unsigned int start_off = __ offset();
|
||||
@ -807,7 +818,7 @@ void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, Phase
|
||||
// Even with PC-relative TOC addressing, we still need this node.
|
||||
// Float loads/stores do not support PC-relative addresses.
|
||||
void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register Rtoc = as_Register(ra_->get_encode(this));
|
||||
__ load_toc(Rtoc);
|
||||
}
|
||||
@ -858,7 +869,7 @@ void MachPrologNode::format(PhaseRegAlloc *ra_, outputStream *st) const {
|
||||
|
||||
void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
Compile* C = ra_->C;
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
__ verify_thread();
|
||||
|
||||
@ -932,7 +943,7 @@ void MachEpilogNode::format(PhaseRegAlloc *ra_, outputStream *os) const {
|
||||
#endif
|
||||
|
||||
void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Compile* C = ra_->C;
|
||||
__ verify_thread();
|
||||
|
||||
@ -949,12 +960,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
|
||||
// Touch the polling page.
|
||||
if (need_polling) {
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
__ z_lg(Z_R1_scratch, Address(Z_thread, Thread::polling_page_offset()));
|
||||
} else {
|
||||
AddressLiteral pp(os::get_polling_page());
|
||||
__ load_const_optimized(Z_R1_scratch, pp);
|
||||
}
|
||||
__ z_lg(Z_R1_scratch, Address(Z_thread, Thread::polling_page_offset()));
|
||||
// We need to mark the code position where the load from the safepoint
|
||||
// polling page was emitted as relocInfo::poll_return_type here.
|
||||
__ relocate(relocInfo::poll_return_type);
|
||||
@ -976,11 +982,6 @@ const Pipeline * MachEpilogNode::pipeline() const {
|
||||
return MachNode::pipeline_class();
|
||||
}
|
||||
|
||||
int MachEpilogNode::safepoint_offset() const {
|
||||
assert(do_polling(), "no return for this epilog node");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// Figure out which register class each belongs in: rc_int, rc_float, rc_stack.
|
||||
@ -1034,7 +1035,7 @@ static unsigned int z_ld_st_helper(CodeBuffer *cbuf, const char *op_str, unsigne
|
||||
|
||||
static unsigned int z_mvc_helper(CodeBuffer *cbuf, int len, int dst_off, int src_off, bool do_print, outputStream *os) {
|
||||
if (cbuf) {
|
||||
MacroAssembler _masm(cbuf);
|
||||
C2_MacroAssembler _masm(cbuf);
|
||||
__ z_mvc(dst_off, len-1, Z_SP, src_off, Z_SP);
|
||||
}
|
||||
|
||||
@ -1108,7 +1109,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
|
||||
// Check for integer reg-reg copy.
|
||||
if (src_lo_rc == rc_int && dst_lo_rc == rc_int) {
|
||||
if (cbuf) {
|
||||
MacroAssembler _masm(cbuf);
|
||||
C2_MacroAssembler _masm(cbuf);
|
||||
Register Rsrc = as_Register(Matcher::_regEncode[src_lo]);
|
||||
Register Rdst = as_Register(Matcher::_regEncode[dst_lo]);
|
||||
__ z_lgr(Rdst, Rsrc);
|
||||
@ -1155,7 +1156,7 @@ uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, PhaseRegAlloc *ra_, boo
|
||||
// Check for float reg-reg copy.
|
||||
if (src_lo_rc == rc_float && dst_lo_rc == rc_float) {
|
||||
if (cbuf) {
|
||||
MacroAssembler _masm(cbuf);
|
||||
C2_MacroAssembler _masm(cbuf);
|
||||
FloatRegister Rsrc = as_FloatRegister(Matcher::_regEncode[src_lo]);
|
||||
FloatRegister Rdst = as_FloatRegister(Matcher::_regEncode[dst_lo]);
|
||||
__ z_ldr(Rdst, Rsrc);
|
||||
@ -1254,7 +1255,7 @@ void MachNopNode::format(PhaseRegAlloc *, outputStream *os) const {
|
||||
#endif
|
||||
|
||||
void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ra_) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
int rem_space = 0;
|
||||
if (!(ra_->C->output()->in_scratch_emit_size())) {
|
||||
@ -1294,7 +1295,7 @@ void BoxLockNode::format(PhaseRegAlloc *ra_, outputStream *os) const {
|
||||
|
||||
// Take care of the size function, if you make changes here!
|
||||
void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
int offset = ra_->reg2offset(in_RegMask(0).find_first_elem());
|
||||
int reg = ra_->get_encode(this);
|
||||
@ -1360,7 +1361,7 @@ void MachUEPNode::format(PhaseRegAlloc *ra_, outputStream *os) const {
|
||||
#endif
|
||||
|
||||
void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
const int ic_miss_offset = 2;
|
||||
|
||||
// Inline_cache contains a klass.
|
||||
@ -1433,6 +1434,13 @@ class HandlerImpl {
|
||||
}
|
||||
};
|
||||
|
||||
class Node::PD {
|
||||
public:
|
||||
enum NodeFlags {
|
||||
_last_flag = Node::_last_flag
|
||||
};
|
||||
};
|
||||
|
||||
%} // end source_hpp section
|
||||
|
||||
source %{
|
||||
@ -1455,7 +1463,7 @@ source %{
|
||||
// aware of the exception.
|
||||
int HandlerImpl::emit_exception_handler(CodeBuffer &cbuf) {
|
||||
Register temp_reg = Z_R1;
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
address base = __ start_a_stub(size_exception_handler());
|
||||
if (base == NULL) {
|
||||
@ -1476,7 +1484,7 @@ int HandlerImpl::emit_exception_handler(CodeBuffer &cbuf) {
|
||||
|
||||
// Emit deopt handler code.
|
||||
int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
address base = __ start_a_stub(size_deopt_handler());
|
||||
|
||||
if (base == NULL) {
|
||||
@ -1803,10 +1811,15 @@ const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||
|
||||
const bool Matcher::convi2l_type_required = true;
|
||||
|
||||
// Should the matcher clone input 'm' of node 'n'?
|
||||
bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Should the Matcher clone shifts on addressing modes, expecting them
|
||||
// to be subsumed into complex addressing expressions or compute them
|
||||
// into registers?
|
||||
bool Matcher::clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
|
||||
bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
|
||||
return clone_base_plus_offset_address(m, mstack, address_visited);
|
||||
}
|
||||
|
||||
@ -1841,13 +1854,13 @@ void Compile::reshape_address(AddPNode* addp) {
|
||||
// needs for encoding need to be specified.
|
||||
encode %{
|
||||
enc_class enc_unimplemented %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ unimplemented("Unimplemented mach node encoding in AD file.", 13);
|
||||
%}
|
||||
|
||||
enc_class enc_untested %{
|
||||
#ifdef ASSERT
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ untested("Untested mach node encoding in AD file.");
|
||||
#endif
|
||||
%}
|
||||
@ -2033,7 +2046,7 @@ encode %{
|
||||
Assembler::reg(Ridx, 12, 48) |
|
||||
Assembler::regz(reg_to_register_object($mem$$base), 16, 48));
|
||||
} else {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ load_const_optimized(Z_R1_scratch, $mem$$disp);
|
||||
if (Ridx != Z_R0) { __ z_agr(Z_R1_scratch, Ridx); }
|
||||
z_emit_inst(cbuf, $secondary |
|
||||
@ -2045,7 +2058,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_brul(Label lbl) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label* p = $lbl$$label;
|
||||
|
||||
// 'p' is `NULL' when this encoding class is used only to
|
||||
@ -2058,7 +2071,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_bru(Label lbl) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label* p = $lbl$$label;
|
||||
|
||||
// 'p' is `NULL' when this encoding class is used only to
|
||||
@ -2071,7 +2084,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_branch_con_far(cmpOp cmp, Label lbl) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label* p = $lbl$$label;
|
||||
|
||||
// 'p' is `NULL' when this encoding class is used only to
|
||||
@ -2084,7 +2097,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_branch_con_short(cmpOp cmp, Label lbl) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label* p = $lbl$$label;
|
||||
|
||||
// 'p' is `NULL' when this encoding class is used only to
|
||||
@ -2097,7 +2110,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_cmpb_regreg(iRegI src1, iRegI src2, Label lbl, cmpOpT cmp) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label* p = $lbl$$label;
|
||||
|
||||
// 'p' is `NULL' when this encoding class is used only to
|
||||
@ -2121,7 +2134,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_cmpb_regregFar(iRegI src1, iRegI src2, Label lbl, cmpOpT cmp) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label* p = $lbl$$label;
|
||||
|
||||
// 'p' is `NULL' when this encoding class is used only to
|
||||
@ -2147,7 +2160,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_cmpb_regimm(iRegI src1, immI8 src2, Label lbl, cmpOpT cmp) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label* p = $lbl$$label;
|
||||
|
||||
// 'p' is `NULL' when this encoding class is used only to
|
||||
@ -2172,7 +2185,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_cmpb_regimmFar(iRegI src1, immI8 src2, Label lbl, cmpOpT cmp) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label* p = $lbl$$label;
|
||||
|
||||
// 'p' is `NULL' when this encoding class is used only to
|
||||
@ -2199,7 +2212,7 @@ encode %{
|
||||
|
||||
// Call from Java to runtime.
|
||||
enc_class z_enc_java_to_runtime_call(method meth) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
// Save return pc before call to the place where we need it, since
|
||||
// callee doesn't.
|
||||
@ -2227,7 +2240,7 @@ encode %{
|
||||
enc_class z_enc_java_static_call(method meth) %{
|
||||
// Call to fixup routine. Fixup routine uses ScopeDesc info to determine
|
||||
// whom we intended to call.
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int ret_offset = 0;
|
||||
|
||||
if (!_method) {
|
||||
@ -2256,7 +2269,7 @@ encode %{
|
||||
|
||||
// Java dynamic call
|
||||
enc_class z_enc_java_dynamic_call(method meth) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
unsigned int start_off = __ offset();
|
||||
|
||||
int vtable_index = this->_vtable_index;
|
||||
@ -2311,7 +2324,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_cmov_reg(cmpOp cmp, iRegI dst, iRegI src) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register Rdst = reg_to_register_object($dst$$reg);
|
||||
Register Rsrc = reg_to_register_object($src$$reg);
|
||||
|
||||
@ -2332,7 +2345,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_cmov_imm(cmpOp cmp, iRegI dst, immI16 src) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register Rdst = reg_to_register_object($dst$$reg);
|
||||
int Csrc = $src$$constant;
|
||||
Assembler::branch_condition cc = (Assembler::branch_condition)$cmp$$cmpcode;
|
||||
@ -2349,7 +2362,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_cctobool(iRegI res) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register Rres = reg_to_register_object($res$$reg);
|
||||
|
||||
if (VM_Version::has_LoadStoreConditional()) {
|
||||
@ -2366,7 +2379,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_casI(iRegI compare_value, iRegI exchange_value, iRegP addr_ptr) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register Rcomp = reg_to_register_object($compare_value$$reg);
|
||||
Register Rnew = reg_to_register_object($exchange_value$$reg);
|
||||
Register Raddr = reg_to_register_object($addr_ptr$$reg);
|
||||
@ -2375,7 +2388,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_casL(iRegL compare_value, iRegL exchange_value, iRegP addr_ptr) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register Rcomp = reg_to_register_object($compare_value$$reg);
|
||||
Register Rnew = reg_to_register_object($exchange_value$$reg);
|
||||
Register Raddr = reg_to_register_object($addr_ptr$$reg);
|
||||
@ -2384,7 +2397,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_SwapI(memoryRSY mem, iRegI dst, iRegI tmp) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register Rdst = reg_to_register_object($dst$$reg);
|
||||
Register Rtmp = reg_to_register_object($tmp$$reg);
|
||||
guarantee(Rdst != Rtmp, "Fix match rule to use TEMP_DEF");
|
||||
@ -2400,7 +2413,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class z_enc_SwapL(memoryRSY mem, iRegL dst, iRegL tmp) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register Rdst = reg_to_register_object($dst$$reg);
|
||||
Register Rtmp = reg_to_register_object($tmp$$reg);
|
||||
guarantee(Rdst != Rtmp, "Fix match rule to use TEMP_DEF");
|
||||
|
@ -3217,7 +3217,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
|
||||
// Save registers, fpu state, and flags
|
||||
map = RegisterSaver::save_live_registers(masm, RegisterSaver::all_registers);
|
||||
|
||||
if (SafepointMechanism::uses_thread_local_poll() && !cause_return) {
|
||||
if (!cause_return) {
|
||||
// Keep a copy of the return pc to detect if it gets modified.
|
||||
__ z_lgr(Z_R6, Z_R14);
|
||||
}
|
||||
@ -3257,7 +3257,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
|
||||
// No exception case
|
||||
__ bind(noException);
|
||||
|
||||
if (SafepointMechanism::uses_thread_local_poll() && !cause_return) {
|
||||
if (!cause_return) {
|
||||
Label no_adjust;
|
||||
// If our stashed return pc was modified by the runtime we avoid touching it
|
||||
const int offset_of_return_pc = _z_abi16(return_pc) + RegisterSaver::live_reg_frame_size(RegisterSaver::all_registers);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2018 SAP SE. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -2379,7 +2379,7 @@ void TemplateTable::_return(TosState state) {
|
||||
__ bind(skip_register_finalizer);
|
||||
}
|
||||
|
||||
if (SafepointMechanism::uses_thread_local_poll() && _desc->bytecode() != Bytecodes::_return_register_finalizer) {
|
||||
if (_desc->bytecode() != Bytecodes::_return_register_finalizer) {
|
||||
Label no_safepoint;
|
||||
const Address poll_byte_addr(Z_thread, in_bytes(Thread::polling_page_offset()) + 7 /* Big Endian */);
|
||||
__ z_tm(poll_byte_addr, SafepointMechanism::poll_bit());
|
||||
|
@ -253,41 +253,48 @@ void VM_Version::initialize() {
|
||||
|
||||
|
||||
void VM_Version::set_features_string() {
|
||||
|
||||
// A note on the _features_string format:
|
||||
// There are jtreg tests checking the _features_string for various properties.
|
||||
// For some strange reason, these tests require the string to contain
|
||||
// only _lowercase_ characters. Keep that in mind when being surprised
|
||||
// about the unusual notation of features - and when adding new ones.
|
||||
// Features may have one comma at the end.
|
||||
// Furthermore, use one, and only one, separator space between features.
|
||||
// Multiple spaces are considered separate tokens, messing up everything.
|
||||
unsigned int ambiguity = 0;
|
||||
_model_string = z_name[0];
|
||||
if (is_z13()) {
|
||||
_features_string = "System z G7-z13 (LDISP_fast, ExtImm, PCrel Load/Store, CmpB, Cond Load/Store, Interlocked Update, TxM, VectorInstr)";
|
||||
_features_string = "system-z, g7-z13, ldisp_fast, extimm, pcrel_load/store, cmpb, cond_load/store, interlocked_update, txm, vectorinstr";
|
||||
_model_string = z_name[7];
|
||||
ambiguity++;
|
||||
}
|
||||
if (is_ec12()) {
|
||||
_features_string = "System z G6-EC12 (LDISP_fast, ExtImm, PCrel Load/Store, CmpB, Cond Load/Store, Interlocked Update, TxM)";
|
||||
_features_string = "system-z, g6-ec12, ldisp_fast, extimm, pcrel_load/store, cmpb, cond_load/store, interlocked_update, txm";
|
||||
_model_string = z_name[6];
|
||||
ambiguity++;
|
||||
}
|
||||
if (is_z196()) {
|
||||
_features_string = "System z G5-z196 (LDISP_fast, ExtImm, PCrel Load/Store, CmpB, Cond Load/Store, Interlocked Update)";
|
||||
_features_string = "system-z, g5-z196, ldisp_fast, extimm, pcrel_load/store, cmpb, cond_load/store, interlocked_update";
|
||||
_model_string = z_name[5];
|
||||
ambiguity++;
|
||||
}
|
||||
if (is_z10()) {
|
||||
_features_string = "System z G4-z10 (LDISP_fast, ExtImm, PCrel Load/Store, CmpB)";
|
||||
_features_string = "system-z, g4-z10, ldisp_fast, extimm, pcrel_load/store, cmpb";
|
||||
_model_string = z_name[4];
|
||||
ambiguity++;
|
||||
}
|
||||
if (is_z9()) {
|
||||
_features_string = "System z G3-z9 (LDISP_fast, ExtImm), out-of-support as of 2016-04-01";
|
||||
_features_string = "system-z, g3-z9, ldisp_fast, extimm, out-of-support as of 2016-04-01";
|
||||
_model_string = z_name[3];
|
||||
ambiguity++;
|
||||
}
|
||||
if (is_z990()) {
|
||||
_features_string = "System z G2-z990 (LDISP_fast), out-of-support as of 2014-07-01";
|
||||
_features_string = "system-z, g2-z990, ldisp_fast, out-of-support as of 2014-07-01";
|
||||
_model_string = z_name[2];
|
||||
ambiguity++;
|
||||
}
|
||||
if (is_z900()) {
|
||||
_features_string = "System z G1-z900 (LDISP), out-of-support as of 2014-07-01";
|
||||
_features_string = "system-z, g1-z900, ldisp, out-of-support as of 2014-07-01";
|
||||
_model_string = z_name[1];
|
||||
ambiguity++;
|
||||
}
|
||||
@ -302,25 +309,24 @@ void VM_Version::set_features_string() {
|
||||
|
||||
if (has_Crypto_AES()) {
|
||||
char buf[256];
|
||||
assert(strlen(_features_string) + 4 + 3*4 + 1 < sizeof(buf), "increase buffer size");
|
||||
jio_snprintf(buf, sizeof(buf), "%s aes%s%s%s", // String 'aes' must be surrounded by spaces so that jtreg tests recognize it.
|
||||
assert(strlen(_features_string) + 3*8 < sizeof(buf), "increase buffer size");
|
||||
jio_snprintf(buf, sizeof(buf), "%s%s%s%s",
|
||||
_features_string,
|
||||
has_Crypto_AES128() ? " 128" : "",
|
||||
has_Crypto_AES192() ? " 192" : "",
|
||||
has_Crypto_AES256() ? " 256" : "");
|
||||
has_Crypto_AES128() ? ", aes128" : "",
|
||||
has_Crypto_AES192() ? ", aes192" : "",
|
||||
has_Crypto_AES256() ? ", aes256" : "");
|
||||
_features_string = os::strdup(buf);
|
||||
}
|
||||
|
||||
if (has_Crypto_SHA()) {
|
||||
char buf[256];
|
||||
assert(strlen(_features_string) + 4 + 2 + 2*4 + 6 + 1 < sizeof(buf), "increase buffer size");
|
||||
// String 'sha1' etc must be surrounded by spaces so that jtreg tests recognize it.
|
||||
jio_snprintf(buf, sizeof(buf), "%s %s%s%s%s",
|
||||
assert(strlen(_features_string) + 6 + 2*8 + 7 < sizeof(buf), "increase buffer size");
|
||||
jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s",
|
||||
_features_string,
|
||||
has_Crypto_SHA1() ? " sha1" : "",
|
||||
has_Crypto_SHA256() ? " sha256" : "",
|
||||
has_Crypto_SHA512() ? " sha512" : "",
|
||||
has_Crypto_GHASH() ? " ghash" : "");
|
||||
has_Crypto_SHA1() ? ", sha1" : "",
|
||||
has_Crypto_SHA256() ? ", sha256" : "",
|
||||
has_Crypto_SHA512() ? ", sha512" : "",
|
||||
has_Crypto_GHASH() ? ", ghash" : "");
|
||||
if (has_Crypto_AES()) { os::free((void *)_features_string); }
|
||||
_features_string = os::strdup(buf);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -1428,11 +1428,7 @@ void LIR_Assembler::return_op(LIR_Opr result) {
|
||||
if (StackReservedPages > 0 && compilation()->has_reserved_stack_access()) {
|
||||
__ reserved_stack_check();
|
||||
}
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
__ ld_ptr(Address(G2_thread, Thread::polling_page_offset()), L0);
|
||||
} else {
|
||||
__ set((intptr_t)os::get_polling_page(), L0);
|
||||
}
|
||||
__ ld_ptr(Address(G2_thread, Thread::polling_page_offset()), L0);
|
||||
__ relocate(relocInfo::poll_return_type);
|
||||
__ ld_ptr(L0, 0, G0);
|
||||
__ ret();
|
||||
@ -1441,11 +1437,7 @@ void LIR_Assembler::return_op(LIR_Opr result) {
|
||||
|
||||
|
||||
int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) {
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
__ ld_ptr(Address(G2_thread, Thread::polling_page_offset()), tmp->as_register());
|
||||
} else {
|
||||
__ set((intptr_t)os::get_polling_page(), tmp->as_register());
|
||||
}
|
||||
__ ld_ptr(Address(G2_thread, Thread::polling_page_offset()), tmp->as_register());
|
||||
if (info != NULL) {
|
||||
add_debug_info_for_branch(info);
|
||||
}
|
||||
|
526
src/hotspot/cpu/sparc/c2_MacroAssembler_sparc.cpp
Normal file
526
src/hotspot/cpu/sparc/c2_MacroAssembler_sparc.cpp
Normal file
@ -0,0 +1,526 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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/assembler.hpp"
|
||||
#include "asm/assembler.inline.hpp"
|
||||
#include "oops/arrayOop.hpp"
|
||||
#include "opto/c2_MacroAssembler.hpp"
|
||||
#include "opto/intrinsicnode.hpp"
|
||||
|
||||
#ifdef PRODUCT
|
||||
#define BLOCK_COMMENT(str) /* nothing */
|
||||
#define STOP(error) stop(error)
|
||||
#else
|
||||
#define BLOCK_COMMENT(str) block_comment(str)
|
||||
#define STOP(error) block_comment(error); stop(error)
|
||||
#endif
|
||||
|
||||
// Compress char[] to byte[] by compressing 16 bytes at once. Return 0 on failure.
|
||||
void C2_MacroAssembler::string_compress_16(Register src, Register dst, Register cnt, Register result,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4,
|
||||
FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, Label& Ldone) {
|
||||
Label Lloop, Lslow;
|
||||
assert(UseVIS >= 3, "VIS3 is required");
|
||||
assert_different_registers(src, dst, cnt, tmp1, tmp2, tmp3, tmp4, result);
|
||||
assert_different_registers(ftmp1, ftmp2, ftmp3);
|
||||
|
||||
// Check if cnt >= 8 (= 16 bytes)
|
||||
cmp(cnt, 8);
|
||||
br(Assembler::less, false, Assembler::pn, Lslow);
|
||||
delayed()->mov(cnt, result); // copy count
|
||||
|
||||
// Check for 8-byte alignment of src and dst
|
||||
or3(src, dst, tmp1);
|
||||
andcc(tmp1, 7, G0);
|
||||
br(Assembler::notZero, false, Assembler::pn, Lslow);
|
||||
delayed()->nop();
|
||||
|
||||
// Set mask for bshuffle instruction
|
||||
Register mask = tmp4;
|
||||
set(0x13579bdf, mask);
|
||||
bmask(mask, G0, G0);
|
||||
|
||||
// Set mask to 0xff00 ff00 ff00 ff00 to check for non-latin1 characters
|
||||
Assembler::sethi(0xff00fc00, mask); // mask = 0x0000 0000 ff00 fc00
|
||||
add(mask, 0x300, mask); // mask = 0x0000 0000 ff00 ff00
|
||||
sllx(mask, 32, tmp1); // tmp1 = 0xff00 ff00 0000 0000
|
||||
or3(mask, tmp1, mask); // mask = 0xff00 ff00 ff00 ff00
|
||||
|
||||
// Load first 8 bytes
|
||||
ldx(src, 0, tmp1);
|
||||
|
||||
bind(Lloop);
|
||||
// Load next 8 bytes
|
||||
ldx(src, 8, tmp2);
|
||||
|
||||
// Check for non-latin1 character by testing if the most significant byte of a char is set.
|
||||
// Although we have to move the data between integer and floating point registers, this is
|
||||
// still faster than the corresponding VIS instructions (ford/fand/fcmpd).
|
||||
or3(tmp1, tmp2, tmp3);
|
||||
btst(tmp3, mask);
|
||||
// annul zeroing if branch is not taken to preserve original count
|
||||
brx(Assembler::notZero, true, Assembler::pn, Ldone);
|
||||
delayed()->mov(G0, result); // 0 - failed
|
||||
|
||||
// Move bytes into float register
|
||||
movxtod(tmp1, ftmp1);
|
||||
movxtod(tmp2, ftmp2);
|
||||
|
||||
// Compress by copying one byte per char from ftmp1 and ftmp2 to ftmp3
|
||||
bshuffle(ftmp1, ftmp2, ftmp3);
|
||||
stf(FloatRegisterImpl::D, ftmp3, dst, 0);
|
||||
|
||||
// Increment addresses and decrement count
|
||||
inc(src, 16);
|
||||
inc(dst, 8);
|
||||
dec(cnt, 8);
|
||||
|
||||
cmp(cnt, 8);
|
||||
// annul LDX if branch is not taken to prevent access past end of string
|
||||
br(Assembler::greaterEqual, true, Assembler::pt, Lloop);
|
||||
delayed()->ldx(src, 0, tmp1);
|
||||
|
||||
// Fallback to slow version
|
||||
bind(Lslow);
|
||||
}
|
||||
|
||||
// Compress char[] to byte[]. Return 0 on failure.
|
||||
void C2_MacroAssembler::string_compress(Register src, Register dst, Register cnt, Register result, Register tmp, Label& Ldone) {
|
||||
Label Lloop;
|
||||
assert_different_registers(src, dst, cnt, tmp, result);
|
||||
|
||||
lduh(src, 0, tmp);
|
||||
|
||||
bind(Lloop);
|
||||
inc(src, sizeof(jchar));
|
||||
cmp(tmp, 0xff);
|
||||
// annul zeroing if branch is not taken to preserve original count
|
||||
br(Assembler::greater, true, Assembler::pn, Ldone); // don't check xcc
|
||||
delayed()->mov(G0, result); // 0 - failed
|
||||
deccc(cnt);
|
||||
stb(tmp, dst, 0);
|
||||
inc(dst);
|
||||
// annul LDUH if branch is not taken to prevent access past end of string
|
||||
br(Assembler::notZero, true, Assembler::pt, Lloop);
|
||||
delayed()->lduh(src, 0, tmp); // hoisted
|
||||
}
|
||||
|
||||
// Inflate byte[] to char[] by inflating 16 bytes at once.
|
||||
void C2_MacroAssembler::string_inflate_16(Register src, Register dst, Register cnt, Register tmp,
|
||||
FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, FloatRegister ftmp4, Label& Ldone) {
|
||||
Label Lloop, Lslow;
|
||||
assert(UseVIS >= 3, "VIS3 is required");
|
||||
assert_different_registers(src, dst, cnt, tmp);
|
||||
assert_different_registers(ftmp1, ftmp2, ftmp3, ftmp4);
|
||||
|
||||
// Check if cnt >= 8 (= 16 bytes)
|
||||
cmp(cnt, 8);
|
||||
br(Assembler::less, false, Assembler::pn, Lslow);
|
||||
delayed()->nop();
|
||||
|
||||
// Check for 8-byte alignment of src and dst
|
||||
or3(src, dst, tmp);
|
||||
andcc(tmp, 7, G0);
|
||||
br(Assembler::notZero, false, Assembler::pn, Lslow);
|
||||
// Initialize float register to zero
|
||||
FloatRegister zerof = ftmp4;
|
||||
delayed()->fzero(FloatRegisterImpl::D, zerof);
|
||||
|
||||
// Load first 8 bytes
|
||||
ldf(FloatRegisterImpl::D, src, 0, ftmp1);
|
||||
|
||||
bind(Lloop);
|
||||
inc(src, 8);
|
||||
dec(cnt, 8);
|
||||
|
||||
// Inflate the string by interleaving each byte from the source array
|
||||
// with a zero byte and storing the result in the destination array.
|
||||
fpmerge(zerof, ftmp1->successor(), ftmp2);
|
||||
stf(FloatRegisterImpl::D, ftmp2, dst, 8);
|
||||
fpmerge(zerof, ftmp1, ftmp3);
|
||||
stf(FloatRegisterImpl::D, ftmp3, dst, 0);
|
||||
|
||||
inc(dst, 16);
|
||||
|
||||
cmp(cnt, 8);
|
||||
// annul LDX if branch is not taken to prevent access past end of string
|
||||
br(Assembler::greaterEqual, true, Assembler::pt, Lloop);
|
||||
delayed()->ldf(FloatRegisterImpl::D, src, 0, ftmp1);
|
||||
|
||||
// Fallback to slow version
|
||||
bind(Lslow);
|
||||
}
|
||||
|
||||
// Inflate byte[] to char[].
|
||||
void C2_MacroAssembler::string_inflate(Register src, Register dst, Register cnt, Register tmp, Label& Ldone) {
|
||||
Label Loop;
|
||||
assert_different_registers(src, dst, cnt, tmp);
|
||||
|
||||
ldub(src, 0, tmp);
|
||||
bind(Loop);
|
||||
inc(src);
|
||||
deccc(cnt);
|
||||
sth(tmp, dst, 0);
|
||||
inc(dst, sizeof(jchar));
|
||||
// annul LDUB if branch is not taken to prevent access past end of string
|
||||
br(Assembler::notZero, true, Assembler::pt, Loop);
|
||||
delayed()->ldub(src, 0, tmp); // hoisted
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::string_compare(Register str1, Register str2,
|
||||
Register cnt1, Register cnt2,
|
||||
Register tmp1, Register tmp2,
|
||||
Register result, int ae) {
|
||||
Label Ldone, Lloop;
|
||||
assert_different_registers(str1, str2, cnt1, cnt2, tmp1, result);
|
||||
int stride1, stride2;
|
||||
|
||||
// Note: Making use of the fact that compareTo(a, b) == -compareTo(b, a)
|
||||
// we interchange str1 and str2 in the UL case and negate the result.
|
||||
// Like this, str1 is always latin1 encoded, expect for the UU case.
|
||||
|
||||
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||
srl(cnt2, 1, cnt2);
|
||||
}
|
||||
|
||||
// See if the lengths are different, and calculate min in cnt1.
|
||||
// Save diff in case we need it for a tie-breaker.
|
||||
Label Lskip;
|
||||
Register diff = tmp1;
|
||||
subcc(cnt1, cnt2, diff);
|
||||
br(Assembler::greater, true, Assembler::pt, Lskip);
|
||||
// cnt2 is shorter, so use its count:
|
||||
delayed()->mov(cnt2, cnt1);
|
||||
bind(Lskip);
|
||||
|
||||
// Rename registers
|
||||
Register limit1 = cnt1;
|
||||
Register limit2 = limit1;
|
||||
Register chr1 = result;
|
||||
Register chr2 = cnt2;
|
||||
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||
// We need an additional register to keep track of two limits
|
||||
assert_different_registers(str1, str2, cnt1, cnt2, tmp1, tmp2, result);
|
||||
limit2 = tmp2;
|
||||
}
|
||||
|
||||
// Is the minimum length zero?
|
||||
cmp(limit1, (int)0); // use cast to resolve overloading ambiguity
|
||||
br(Assembler::equal, true, Assembler::pn, Ldone);
|
||||
// result is difference in lengths
|
||||
if (ae == StrIntrinsicNode::UU) {
|
||||
delayed()->sra(diff, 1, result); // Divide by 2 to get number of chars
|
||||
} else {
|
||||
delayed()->mov(diff, result);
|
||||
}
|
||||
|
||||
// Load first characters
|
||||
if (ae == StrIntrinsicNode::LL) {
|
||||
stride1 = stride2 = sizeof(jbyte);
|
||||
ldub(str1, 0, chr1);
|
||||
ldub(str2, 0, chr2);
|
||||
} else if (ae == StrIntrinsicNode::UU) {
|
||||
stride1 = stride2 = sizeof(jchar);
|
||||
lduh(str1, 0, chr1);
|
||||
lduh(str2, 0, chr2);
|
||||
} else {
|
||||
stride1 = sizeof(jbyte);
|
||||
stride2 = sizeof(jchar);
|
||||
ldub(str1, 0, chr1);
|
||||
lduh(str2, 0, chr2);
|
||||
}
|
||||
|
||||
// Compare first characters
|
||||
subcc(chr1, chr2, chr1);
|
||||
br(Assembler::notZero, false, Assembler::pt, Ldone);
|
||||
assert(chr1 == result, "result must be pre-placed");
|
||||
delayed()->nop();
|
||||
|
||||
// Check if the strings start at same location
|
||||
cmp(str1, str2);
|
||||
brx(Assembler::equal, true, Assembler::pn, Ldone);
|
||||
delayed()->mov(G0, result); // result is zero
|
||||
|
||||
// We have no guarantee that on 64 bit the higher half of limit is 0
|
||||
signx(limit1);
|
||||
|
||||
// Get limit
|
||||
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||
sll(limit1, 1, limit2);
|
||||
subcc(limit2, stride2, chr2);
|
||||
}
|
||||
subcc(limit1, stride1, chr1);
|
||||
br(Assembler::zero, true, Assembler::pn, Ldone);
|
||||
// result is difference in lengths
|
||||
if (ae == StrIntrinsicNode::UU) {
|
||||
delayed()->sra(diff, 1, result); // Divide by 2 to get number of chars
|
||||
} else {
|
||||
delayed()->mov(diff, result);
|
||||
}
|
||||
|
||||
// Shift str1 and str2 to the end of the arrays, negate limit
|
||||
add(str1, limit1, str1);
|
||||
add(str2, limit2, str2);
|
||||
neg(chr1, limit1); // limit1 = -(limit1-stride1)
|
||||
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||
neg(chr2, limit2); // limit2 = -(limit2-stride2)
|
||||
}
|
||||
|
||||
// Compare the rest of the characters
|
||||
load_sized_value(Address(str1, limit1), chr1, (ae == StrIntrinsicNode::UU) ? 2 : 1, false);
|
||||
|
||||
bind(Lloop);
|
||||
load_sized_value(Address(str2, limit2), chr2, (ae == StrIntrinsicNode::LL) ? 1 : 2, false);
|
||||
|
||||
subcc(chr1, chr2, chr1);
|
||||
br(Assembler::notZero, false, Assembler::pt, Ldone);
|
||||
assert(chr1 == result, "result must be pre-placed");
|
||||
delayed()->inccc(limit1, stride1);
|
||||
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||
inccc(limit2, stride2);
|
||||
}
|
||||
|
||||
// annul LDUB if branch is not taken to prevent access past end of string
|
||||
br(Assembler::notZero, true, Assembler::pt, Lloop);
|
||||
delayed()->load_sized_value(Address(str1, limit1), chr1, (ae == StrIntrinsicNode::UU) ? 2 : 1, false);
|
||||
|
||||
// If strings are equal up to min length, return the length difference.
|
||||
if (ae == StrIntrinsicNode::UU) {
|
||||
// Divide by 2 to get number of chars
|
||||
sra(diff, 1, result);
|
||||
} else {
|
||||
mov(diff, result);
|
||||
}
|
||||
|
||||
// Otherwise, return the difference between the first mismatched chars.
|
||||
bind(Ldone);
|
||||
if(ae == StrIntrinsicNode::UL) {
|
||||
// Negate result (see note above)
|
||||
neg(result);
|
||||
}
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::array_equals(bool is_array_equ, Register ary1, Register ary2,
|
||||
Register limit, Register tmp, Register result, bool is_byte) {
|
||||
Label Ldone, Lloop, Lremaining;
|
||||
assert_different_registers(ary1, ary2, limit, tmp, result);
|
||||
|
||||
int length_offset = arrayOopDesc::length_offset_in_bytes();
|
||||
int base_offset = arrayOopDesc::base_offset_in_bytes(is_byte ? T_BYTE : T_CHAR);
|
||||
assert(base_offset % 8 == 0, "Base offset must be 8-byte aligned");
|
||||
|
||||
if (is_array_equ) {
|
||||
// return true if the same array
|
||||
cmp(ary1, ary2);
|
||||
brx(Assembler::equal, true, Assembler::pn, Ldone);
|
||||
delayed()->mov(1, result); // equal
|
||||
|
||||
br_null(ary1, true, Assembler::pn, Ldone);
|
||||
delayed()->clr(result); // not equal
|
||||
|
||||
br_null(ary2, true, Assembler::pn, Ldone);
|
||||
delayed()->clr(result); // not equal
|
||||
|
||||
// load the lengths of arrays
|
||||
ld(Address(ary1, length_offset), limit);
|
||||
ld(Address(ary2, length_offset), tmp);
|
||||
|
||||
// return false if the two arrays are not equal length
|
||||
cmp(limit, tmp);
|
||||
br(Assembler::notEqual, true, Assembler::pn, Ldone);
|
||||
delayed()->clr(result); // not equal
|
||||
}
|
||||
|
||||
cmp_zero_and_br(Assembler::zero, limit, Ldone, true, Assembler::pn);
|
||||
delayed()->mov(1, result); // zero-length arrays are equal
|
||||
|
||||
if (is_array_equ) {
|
||||
// load array addresses
|
||||
add(ary1, base_offset, ary1);
|
||||
add(ary2, base_offset, ary2);
|
||||
// set byte count
|
||||
if (!is_byte) {
|
||||
sll(limit, exact_log2(sizeof(jchar)), limit);
|
||||
}
|
||||
} else {
|
||||
// We have no guarantee that on 64 bit the higher half of limit is 0
|
||||
signx(limit);
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
// Sanity check for doubleword (8-byte) alignment of ary1 and ary2.
|
||||
// Guaranteed on 64-bit systems (see arrayOopDesc::header_size_in_bytes()).
|
||||
Label Laligned;
|
||||
or3(ary1, ary2, tmp);
|
||||
andcc(tmp, 7, tmp);
|
||||
br_null_short(tmp, Assembler::pn, Laligned);
|
||||
STOP("First array element is not 8-byte aligned.");
|
||||
should_not_reach_here();
|
||||
bind(Laligned);
|
||||
#endif
|
||||
|
||||
// Shift ary1 and ary2 to the end of the arrays, negate limit
|
||||
add(ary1, limit, ary1);
|
||||
add(ary2, limit, ary2);
|
||||
neg(limit, limit);
|
||||
|
||||
// MAIN LOOP
|
||||
// Load and compare array elements of size 'byte_width' until the elements are not
|
||||
// equal or we reached the end of the arrays. If the size of the arrays is not a
|
||||
// multiple of 'byte_width', we simply read over the end of the array, bail out and
|
||||
// compare the remaining bytes below by skipping the garbage bytes.
|
||||
ldx(ary1, limit, result);
|
||||
bind(Lloop);
|
||||
ldx(ary2, limit, tmp);
|
||||
inccc(limit, 8);
|
||||
// Bail out if we reached the end (but still do the comparison)
|
||||
br(Assembler::positive, false, Assembler::pn, Lremaining);
|
||||
delayed()->cmp(result, tmp);
|
||||
// Check equality of elements
|
||||
brx(Assembler::equal, false, Assembler::pt, target(Lloop));
|
||||
delayed()->ldx(ary1, limit, result);
|
||||
|
||||
ba(Ldone);
|
||||
delayed()->clr(result); // not equal
|
||||
|
||||
// TAIL COMPARISON
|
||||
// We got here because we reached the end of the arrays. 'limit' is the number of
|
||||
// garbage bytes we may have compared by reading over the end of the arrays. Shift
|
||||
// out the garbage and compare the remaining elements.
|
||||
bind(Lremaining);
|
||||
// Optimistic shortcut: elements potentially including garbage are equal
|
||||
brx(Assembler::equal, true, Assembler::pt, target(Ldone));
|
||||
delayed()->mov(1, result); // equal
|
||||
// Shift 'limit' bytes to the right and compare
|
||||
sll(limit, 3, limit); // bytes to bits
|
||||
srlx(result, limit, result);
|
||||
srlx(tmp, limit, tmp);
|
||||
cmp(result, tmp);
|
||||
clr(result);
|
||||
movcc(Assembler::equal, false, xcc, 1, result);
|
||||
|
||||
bind(Ldone);
|
||||
}
|
||||
|
||||
void C2_MacroAssembler::has_negatives(Register inp, Register size, Register result, Register t2, Register t3, Register t4, Register t5) {
|
||||
|
||||
// test for negative bytes in input string of a given size
|
||||
// result 1 if found, 0 otherwise.
|
||||
|
||||
Label Lcore, Ltail, Lreturn, Lcore_rpt;
|
||||
|
||||
assert_different_registers(inp, size, t2, t3, t4, t5, result);
|
||||
|
||||
Register i = result; // result used as integer index i until very end
|
||||
Register lmask = t2; // t2 is aliased to lmask
|
||||
|
||||
// INITIALIZATION
|
||||
// ===========================================================
|
||||
// initialize highbits mask -> lmask = 0x8080808080808080 (8B/64b)
|
||||
// compute unaligned offset -> i
|
||||
// compute core end index -> t5
|
||||
Assembler::sethi(0x80808000, t2); //! sethi macro fails to emit optimal
|
||||
add(t2, 0x80, t2);
|
||||
sllx(t2, 32, t3);
|
||||
or3(t3, t2, lmask); // 0x8080808080808080 -> lmask
|
||||
sra(size,0,size);
|
||||
andcc(inp, 0x7, i); // unaligned offset -> i
|
||||
br(Assembler::zero, true, Assembler::pn, Lcore); // starts 8B aligned?
|
||||
delayed()->add(size, -8, t5); // (annuled) core end index -> t5
|
||||
|
||||
// ===========================================================
|
||||
|
||||
// UNALIGNED HEAD
|
||||
// ===========================================================
|
||||
// * unaligned head handling: grab aligned 8B containing unaligned inp(ut)
|
||||
// * obliterate (ignore) bytes outside string by shifting off reg ends
|
||||
// * compare with bitmask, short circuit return true if one or more high
|
||||
// bits set.
|
||||
cmp(size, 0);
|
||||
br(Assembler::zero, true, Assembler::pn, Lreturn); // short-circuit?
|
||||
delayed()->mov(0,result); // annuled so i not clobbered for following
|
||||
neg(i, t4);
|
||||
add(i, size, t5);
|
||||
ldx(inp, t4, t3); // raw aligned 8B containing unaligned head -> t3
|
||||
mov(8, t4);
|
||||
sub(t4, t5, t4);
|
||||
sra(t4, 31, t5);
|
||||
andn(t4, t5, t5);
|
||||
add(i, t5, t4);
|
||||
sll(t5, 3, t5);
|
||||
sll(t4, 3, t4); // # bits to shift right, left -> t5,t4
|
||||
srlx(t3, t5, t3);
|
||||
sllx(t3, t4, t3); // bytes outside string in 8B header obliterated -> t3
|
||||
andcc(lmask, t3, G0);
|
||||
brx(Assembler::notZero, true, Assembler::pn, Lreturn); // short circuit?
|
||||
delayed()->mov(1,result); // annuled so i not clobbered for following
|
||||
add(size, -8, t5); // core end index -> t5
|
||||
mov(8, t4);
|
||||
sub(t4, i, i); // # bytes examined in unalgn head (<8) -> i
|
||||
// ===========================================================
|
||||
|
||||
// ALIGNED CORE
|
||||
// ===========================================================
|
||||
// * iterate index i over aligned 8B sections of core, comparing with
|
||||
// bitmask, short circuit return true if one or more high bits set
|
||||
// t5 contains core end index/loop limit which is the index
|
||||
// of the MSB of last (unaligned) 8B fully contained in the string.
|
||||
// inp contains address of first byte in string/array
|
||||
// lmask contains 8B high bit mask for comparison
|
||||
// i contains next index to be processed (adr. inp+i is on 8B boundary)
|
||||
bind(Lcore);
|
||||
cmp_and_br_short(i, t5, Assembler::greater, Assembler::pn, Ltail);
|
||||
bind(Lcore_rpt);
|
||||
ldx(inp, i, t3);
|
||||
andcc(t3, lmask, G0);
|
||||
brx(Assembler::notZero, true, Assembler::pn, Lreturn);
|
||||
delayed()->mov(1, result); // annuled so i not clobbered for following
|
||||
add(i, 8, i);
|
||||
cmp_and_br_short(i, t5, Assembler::lessEqual, Assembler::pn, Lcore_rpt);
|
||||
// ===========================================================
|
||||
|
||||
// ALIGNED TAIL (<8B)
|
||||
// ===========================================================
|
||||
// handle aligned tail of 7B or less as complete 8B, obliterating end of
|
||||
// string bytes by shifting them off end, compare what's left with bitmask
|
||||
// inp contains address of first byte in string/array
|
||||
// lmask contains 8B high bit mask for comparison
|
||||
// i contains next index to be processed (adr. inp+i is on 8B boundary)
|
||||
bind(Ltail);
|
||||
subcc(size, i, t4); // # of remaining bytes in string -> t4
|
||||
// return 0 if no more remaining bytes
|
||||
br(Assembler::lessEqual, true, Assembler::pn, Lreturn);
|
||||
delayed()->mov(0, result); // annuled so i not clobbered for following
|
||||
ldx(inp, i, t3); // load final 8B (aligned) containing tail -> t3
|
||||
mov(8, t5);
|
||||
sub(t5, t4, t4);
|
||||
mov(0, result); // ** i clobbered at this point
|
||||
sll(t4, 3, t4); // bits beyond end of string -> t4
|
||||
srlx(t3, t4, t3); // bytes beyond end now obliterated -> t3
|
||||
andcc(lmask, t3, G0);
|
||||
movcc(Assembler::notZero, false, xcc, 1, result);
|
||||
bind(Lreturn);
|
||||
}
|
||||
|
58
src/hotspot/cpu/sparc/c2_MacroAssembler_sparc.hpp
Normal file
58
src/hotspot/cpu/sparc/c2_MacroAssembler_sparc.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CPU_SPARC_C2_MACROASSEMBLER_SPARC_HPP
|
||||
#define CPU_SPARC_C2_MACROASSEMBLER_SPARC_HPP
|
||||
|
||||
// C2_MacroAssembler contains high-level macros for C2
|
||||
|
||||
public:
|
||||
// Compress char[] to byte[] by compressing 16 bytes at once. Return 0 on failure.
|
||||
void string_compress_16(Register src, Register dst, Register cnt, Register result,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4,
|
||||
FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, Label& Ldone);
|
||||
|
||||
// Compress char[] to byte[]. Return 0 on failure.
|
||||
void string_compress(Register src, Register dst, Register cnt, Register tmp, Register result, Label& Ldone);
|
||||
|
||||
// Inflate byte[] to char[] by inflating 16 bytes at once.
|
||||
void string_inflate_16(Register src, Register dst, Register cnt, Register tmp,
|
||||
FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, FloatRegister ftmp4, Label& Ldone);
|
||||
|
||||
// Inflate byte[] to char[].
|
||||
void string_inflate(Register src, Register dst, Register cnt, Register tmp, Label& Ldone);
|
||||
|
||||
void string_compare(Register str1, Register str2,
|
||||
Register cnt1, Register cnt2,
|
||||
Register tmp1, Register tmp2,
|
||||
Register result, int ae);
|
||||
|
||||
void array_equals(bool is_array_equ, Register ary1, Register ary2,
|
||||
Register limit, Register tmp, Register result, bool is_byte);
|
||||
// test for negative bytes in input string of a given size, result 0 if none
|
||||
void has_negatives(Register inp, Register size, Register result,
|
||||
Register t2, Register t3, Register t4,
|
||||
Register t5);
|
||||
|
||||
#endif // CPU_SPARC_C2_MACROASSEMBLER_SPARC_HPP
|
@ -550,9 +550,10 @@ frame frame::sender(RegisterMap* map) const {
|
||||
|
||||
|
||||
void frame::patch_pc(Thread* thread, address pc) {
|
||||
assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
|
||||
vmassert(_deopt_state != unknown, "frame is unpatchable");
|
||||
if(thread == Thread::current()) {
|
||||
StubRoutines::Sparc::flush_callers_register_windows_func()();
|
||||
if (thread == Thread::current()) {
|
||||
StubRoutines::Sparc::flush_callers_register_windows_func()();
|
||||
}
|
||||
if (TracePcPatching) {
|
||||
// QQQ this assert is invalid (or too strong anyway) sice _pc could
|
||||
@ -561,9 +562,7 @@ void frame::patch_pc(Thread* thread, address pc) {
|
||||
tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]",
|
||||
p2i(O7_addr()), p2i(_pc), p2i(pc));
|
||||
}
|
||||
_cb = CodeCache::find_blob(pc);
|
||||
*O7_addr() = pc - pc_return_offset;
|
||||
_cb = CodeCache::find_blob(_pc);
|
||||
address original_pc = CompiledMethod::get_deopt_original_pc(this);
|
||||
if (original_pc != NULL) {
|
||||
assert(original_pc == _pc, "expected original to be stored before patching");
|
||||
|
@ -56,7 +56,4 @@ const bool CCallingConventionRequiresIntsAsLongs = true;
|
||||
#define SUPPORT_RESERVED_STACK_AREA
|
||||
#endif
|
||||
|
||||
// SPARC have implemented the local polling
|
||||
#define THREAD_LOCAL_POLL
|
||||
|
||||
#endif // CPU_SPARC_GLOBALDEFINITIONS_SPARC_HPP
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -271,7 +271,7 @@ void InterpreterMacroAssembler::dispatch_Lbyte_code(TosState state, address* tab
|
||||
AddressLiteral tbl(table);
|
||||
Label dispatch;
|
||||
|
||||
if (SafepointMechanism::uses_thread_local_poll() && generate_poll) {
|
||||
if (generate_poll) {
|
||||
AddressLiteral sfpt_tbl(Interpreter::safept_table(state));
|
||||
Label no_safepoint;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -49,9 +49,6 @@
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
#ifdef COMPILER2
|
||||
#include "opto/intrinsicnode.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef PRODUCT
|
||||
#define BLOCK_COMMENT(str) /* nothing */
|
||||
@ -239,18 +236,10 @@ void MacroAssembler::breakpoint_trap() {
|
||||
}
|
||||
|
||||
void MacroAssembler::safepoint_poll(Label& slow_path, bool a, Register thread_reg, Register temp_reg) {
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
ldx(Address(thread_reg, Thread::polling_page_offset()), temp_reg, 0);
|
||||
// Armed page has poll bit set.
|
||||
and3(temp_reg, SafepointMechanism::poll_bit(), temp_reg);
|
||||
br_notnull(temp_reg, a, Assembler::pn, slow_path);
|
||||
} else {
|
||||
AddressLiteral sync_state(SafepointSynchronize::address_of_state());
|
||||
|
||||
load_contents(sync_state, temp_reg);
|
||||
cmp(temp_reg, SafepointSynchronize::_not_synchronized);
|
||||
br(Assembler::notEqual, a, Assembler::pn, slow_path);
|
||||
}
|
||||
ldx(Address(thread_reg, Thread::polling_page_offset()), temp_reg, 0);
|
||||
// Armed page has poll bit set.
|
||||
and3(temp_reg, SafepointMechanism::poll_bit(), temp_reg);
|
||||
br_notnull(temp_reg, a, Assembler::pn, slow_path);
|
||||
}
|
||||
|
||||
void MacroAssembler::enter() {
|
||||
@ -3436,498 +3425,6 @@ void MacroAssembler::reinit_heapbase() {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef COMPILER2
|
||||
|
||||
// Compress char[] to byte[] by compressing 16 bytes at once. Return 0 on failure.
|
||||
void MacroAssembler::string_compress_16(Register src, Register dst, Register cnt, Register result,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4,
|
||||
FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, Label& Ldone) {
|
||||
Label Lloop, Lslow;
|
||||
assert(UseVIS >= 3, "VIS3 is required");
|
||||
assert_different_registers(src, dst, cnt, tmp1, tmp2, tmp3, tmp4, result);
|
||||
assert_different_registers(ftmp1, ftmp2, ftmp3);
|
||||
|
||||
// Check if cnt >= 8 (= 16 bytes)
|
||||
cmp(cnt, 8);
|
||||
br(Assembler::less, false, Assembler::pn, Lslow);
|
||||
delayed()->mov(cnt, result); // copy count
|
||||
|
||||
// Check for 8-byte alignment of src and dst
|
||||
or3(src, dst, tmp1);
|
||||
andcc(tmp1, 7, G0);
|
||||
br(Assembler::notZero, false, Assembler::pn, Lslow);
|
||||
delayed()->nop();
|
||||
|
||||
// Set mask for bshuffle instruction
|
||||
Register mask = tmp4;
|
||||
set(0x13579bdf, mask);
|
||||
bmask(mask, G0, G0);
|
||||
|
||||
// Set mask to 0xff00 ff00 ff00 ff00 to check for non-latin1 characters
|
||||
Assembler::sethi(0xff00fc00, mask); // mask = 0x0000 0000 ff00 fc00
|
||||
add(mask, 0x300, mask); // mask = 0x0000 0000 ff00 ff00
|
||||
sllx(mask, 32, tmp1); // tmp1 = 0xff00 ff00 0000 0000
|
||||
or3(mask, tmp1, mask); // mask = 0xff00 ff00 ff00 ff00
|
||||
|
||||
// Load first 8 bytes
|
||||
ldx(src, 0, tmp1);
|
||||
|
||||
bind(Lloop);
|
||||
// Load next 8 bytes
|
||||
ldx(src, 8, tmp2);
|
||||
|
||||
// Check for non-latin1 character by testing if the most significant byte of a char is set.
|
||||
// Although we have to move the data between integer and floating point registers, this is
|
||||
// still faster than the corresponding VIS instructions (ford/fand/fcmpd).
|
||||
or3(tmp1, tmp2, tmp3);
|
||||
btst(tmp3, mask);
|
||||
// annul zeroing if branch is not taken to preserve original count
|
||||
brx(Assembler::notZero, true, Assembler::pn, Ldone);
|
||||
delayed()->mov(G0, result); // 0 - failed
|
||||
|
||||
// Move bytes into float register
|
||||
movxtod(tmp1, ftmp1);
|
||||
movxtod(tmp2, ftmp2);
|
||||
|
||||
// Compress by copying one byte per char from ftmp1 and ftmp2 to ftmp3
|
||||
bshuffle(ftmp1, ftmp2, ftmp3);
|
||||
stf(FloatRegisterImpl::D, ftmp3, dst, 0);
|
||||
|
||||
// Increment addresses and decrement count
|
||||
inc(src, 16);
|
||||
inc(dst, 8);
|
||||
dec(cnt, 8);
|
||||
|
||||
cmp(cnt, 8);
|
||||
// annul LDX if branch is not taken to prevent access past end of string
|
||||
br(Assembler::greaterEqual, true, Assembler::pt, Lloop);
|
||||
delayed()->ldx(src, 0, tmp1);
|
||||
|
||||
// Fallback to slow version
|
||||
bind(Lslow);
|
||||
}
|
||||
|
||||
// Compress char[] to byte[]. Return 0 on failure.
|
||||
void MacroAssembler::string_compress(Register src, Register dst, Register cnt, Register result, Register tmp, Label& Ldone) {
|
||||
Label Lloop;
|
||||
assert_different_registers(src, dst, cnt, tmp, result);
|
||||
|
||||
lduh(src, 0, tmp);
|
||||
|
||||
bind(Lloop);
|
||||
inc(src, sizeof(jchar));
|
||||
cmp(tmp, 0xff);
|
||||
// annul zeroing if branch is not taken to preserve original count
|
||||
br(Assembler::greater, true, Assembler::pn, Ldone); // don't check xcc
|
||||
delayed()->mov(G0, result); // 0 - failed
|
||||
deccc(cnt);
|
||||
stb(tmp, dst, 0);
|
||||
inc(dst);
|
||||
// annul LDUH if branch is not taken to prevent access past end of string
|
||||
br(Assembler::notZero, true, Assembler::pt, Lloop);
|
||||
delayed()->lduh(src, 0, tmp); // hoisted
|
||||
}
|
||||
|
||||
// Inflate byte[] to char[] by inflating 16 bytes at once.
|
||||
void MacroAssembler::string_inflate_16(Register src, Register dst, Register cnt, Register tmp,
|
||||
FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, FloatRegister ftmp4, Label& Ldone) {
|
||||
Label Lloop, Lslow;
|
||||
assert(UseVIS >= 3, "VIS3 is required");
|
||||
assert_different_registers(src, dst, cnt, tmp);
|
||||
assert_different_registers(ftmp1, ftmp2, ftmp3, ftmp4);
|
||||
|
||||
// Check if cnt >= 8 (= 16 bytes)
|
||||
cmp(cnt, 8);
|
||||
br(Assembler::less, false, Assembler::pn, Lslow);
|
||||
delayed()->nop();
|
||||
|
||||
// Check for 8-byte alignment of src and dst
|
||||
or3(src, dst, tmp);
|
||||
andcc(tmp, 7, G0);
|
||||
br(Assembler::notZero, false, Assembler::pn, Lslow);
|
||||
// Initialize float register to zero
|
||||
FloatRegister zerof = ftmp4;
|
||||
delayed()->fzero(FloatRegisterImpl::D, zerof);
|
||||
|
||||
// Load first 8 bytes
|
||||
ldf(FloatRegisterImpl::D, src, 0, ftmp1);
|
||||
|
||||
bind(Lloop);
|
||||
inc(src, 8);
|
||||
dec(cnt, 8);
|
||||
|
||||
// Inflate the string by interleaving each byte from the source array
|
||||
// with a zero byte and storing the result in the destination array.
|
||||
fpmerge(zerof, ftmp1->successor(), ftmp2);
|
||||
stf(FloatRegisterImpl::D, ftmp2, dst, 8);
|
||||
fpmerge(zerof, ftmp1, ftmp3);
|
||||
stf(FloatRegisterImpl::D, ftmp3, dst, 0);
|
||||
|
||||
inc(dst, 16);
|
||||
|
||||
cmp(cnt, 8);
|
||||
// annul LDX if branch is not taken to prevent access past end of string
|
||||
br(Assembler::greaterEqual, true, Assembler::pt, Lloop);
|
||||
delayed()->ldf(FloatRegisterImpl::D, src, 0, ftmp1);
|
||||
|
||||
// Fallback to slow version
|
||||
bind(Lslow);
|
||||
}
|
||||
|
||||
// Inflate byte[] to char[].
|
||||
void MacroAssembler::string_inflate(Register src, Register dst, Register cnt, Register tmp, Label& Ldone) {
|
||||
Label Loop;
|
||||
assert_different_registers(src, dst, cnt, tmp);
|
||||
|
||||
ldub(src, 0, tmp);
|
||||
bind(Loop);
|
||||
inc(src);
|
||||
deccc(cnt);
|
||||
sth(tmp, dst, 0);
|
||||
inc(dst, sizeof(jchar));
|
||||
// annul LDUB if branch is not taken to prevent access past end of string
|
||||
br(Assembler::notZero, true, Assembler::pt, Loop);
|
||||
delayed()->ldub(src, 0, tmp); // hoisted
|
||||
}
|
||||
|
||||
void MacroAssembler::string_compare(Register str1, Register str2,
|
||||
Register cnt1, Register cnt2,
|
||||
Register tmp1, Register tmp2,
|
||||
Register result, int ae) {
|
||||
Label Ldone, Lloop;
|
||||
assert_different_registers(str1, str2, cnt1, cnt2, tmp1, result);
|
||||
int stride1, stride2;
|
||||
|
||||
// Note: Making use of the fact that compareTo(a, b) == -compareTo(b, a)
|
||||
// we interchange str1 and str2 in the UL case and negate the result.
|
||||
// Like this, str1 is always latin1 encoded, expect for the UU case.
|
||||
|
||||
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||
srl(cnt2, 1, cnt2);
|
||||
}
|
||||
|
||||
// See if the lengths are different, and calculate min in cnt1.
|
||||
// Save diff in case we need it for a tie-breaker.
|
||||
Label Lskip;
|
||||
Register diff = tmp1;
|
||||
subcc(cnt1, cnt2, diff);
|
||||
br(Assembler::greater, true, Assembler::pt, Lskip);
|
||||
// cnt2 is shorter, so use its count:
|
||||
delayed()->mov(cnt2, cnt1);
|
||||
bind(Lskip);
|
||||
|
||||
// Rename registers
|
||||
Register limit1 = cnt1;
|
||||
Register limit2 = limit1;
|
||||
Register chr1 = result;
|
||||
Register chr2 = cnt2;
|
||||
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||
// We need an additional register to keep track of two limits
|
||||
assert_different_registers(str1, str2, cnt1, cnt2, tmp1, tmp2, result);
|
||||
limit2 = tmp2;
|
||||
}
|
||||
|
||||
// Is the minimum length zero?
|
||||
cmp(limit1, (int)0); // use cast to resolve overloading ambiguity
|
||||
br(Assembler::equal, true, Assembler::pn, Ldone);
|
||||
// result is difference in lengths
|
||||
if (ae == StrIntrinsicNode::UU) {
|
||||
delayed()->sra(diff, 1, result); // Divide by 2 to get number of chars
|
||||
} else {
|
||||
delayed()->mov(diff, result);
|
||||
}
|
||||
|
||||
// Load first characters
|
||||
if (ae == StrIntrinsicNode::LL) {
|
||||
stride1 = stride2 = sizeof(jbyte);
|
||||
ldub(str1, 0, chr1);
|
||||
ldub(str2, 0, chr2);
|
||||
} else if (ae == StrIntrinsicNode::UU) {
|
||||
stride1 = stride2 = sizeof(jchar);
|
||||
lduh(str1, 0, chr1);
|
||||
lduh(str2, 0, chr2);
|
||||
} else {
|
||||
stride1 = sizeof(jbyte);
|
||||
stride2 = sizeof(jchar);
|
||||
ldub(str1, 0, chr1);
|
||||
lduh(str2, 0, chr2);
|
||||
}
|
||||
|
||||
// Compare first characters
|
||||
subcc(chr1, chr2, chr1);
|
||||
br(Assembler::notZero, false, Assembler::pt, Ldone);
|
||||
assert(chr1 == result, "result must be pre-placed");
|
||||
delayed()->nop();
|
||||
|
||||
// Check if the strings start at same location
|
||||
cmp(str1, str2);
|
||||
brx(Assembler::equal, true, Assembler::pn, Ldone);
|
||||
delayed()->mov(G0, result); // result is zero
|
||||
|
||||
// We have no guarantee that on 64 bit the higher half of limit is 0
|
||||
signx(limit1);
|
||||
|
||||
// Get limit
|
||||
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||
sll(limit1, 1, limit2);
|
||||
subcc(limit2, stride2, chr2);
|
||||
}
|
||||
subcc(limit1, stride1, chr1);
|
||||
br(Assembler::zero, true, Assembler::pn, Ldone);
|
||||
// result is difference in lengths
|
||||
if (ae == StrIntrinsicNode::UU) {
|
||||
delayed()->sra(diff, 1, result); // Divide by 2 to get number of chars
|
||||
} else {
|
||||
delayed()->mov(diff, result);
|
||||
}
|
||||
|
||||
// Shift str1 and str2 to the end of the arrays, negate limit
|
||||
add(str1, limit1, str1);
|
||||
add(str2, limit2, str2);
|
||||
neg(chr1, limit1); // limit1 = -(limit1-stride1)
|
||||
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||
neg(chr2, limit2); // limit2 = -(limit2-stride2)
|
||||
}
|
||||
|
||||
// Compare the rest of the characters
|
||||
load_sized_value(Address(str1, limit1), chr1, (ae == StrIntrinsicNode::UU) ? 2 : 1, false);
|
||||
|
||||
bind(Lloop);
|
||||
load_sized_value(Address(str2, limit2), chr2, (ae == StrIntrinsicNode::LL) ? 1 : 2, false);
|
||||
|
||||
subcc(chr1, chr2, chr1);
|
||||
br(Assembler::notZero, false, Assembler::pt, Ldone);
|
||||
assert(chr1 == result, "result must be pre-placed");
|
||||
delayed()->inccc(limit1, stride1);
|
||||
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||
inccc(limit2, stride2);
|
||||
}
|
||||
|
||||
// annul LDUB if branch is not taken to prevent access past end of string
|
||||
br(Assembler::notZero, true, Assembler::pt, Lloop);
|
||||
delayed()->load_sized_value(Address(str1, limit1), chr1, (ae == StrIntrinsicNode::UU) ? 2 : 1, false);
|
||||
|
||||
// If strings are equal up to min length, return the length difference.
|
||||
if (ae == StrIntrinsicNode::UU) {
|
||||
// Divide by 2 to get number of chars
|
||||
sra(diff, 1, result);
|
||||
} else {
|
||||
mov(diff, result);
|
||||
}
|
||||
|
||||
// Otherwise, return the difference between the first mismatched chars.
|
||||
bind(Ldone);
|
||||
if(ae == StrIntrinsicNode::UL) {
|
||||
// Negate result (see note above)
|
||||
neg(result);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroAssembler::array_equals(bool is_array_equ, Register ary1, Register ary2,
|
||||
Register limit, Register tmp, Register result, bool is_byte) {
|
||||
Label Ldone, Lloop, Lremaining;
|
||||
assert_different_registers(ary1, ary2, limit, tmp, result);
|
||||
|
||||
int length_offset = arrayOopDesc::length_offset_in_bytes();
|
||||
int base_offset = arrayOopDesc::base_offset_in_bytes(is_byte ? T_BYTE : T_CHAR);
|
||||
assert(base_offset % 8 == 0, "Base offset must be 8-byte aligned");
|
||||
|
||||
if (is_array_equ) {
|
||||
// return true if the same array
|
||||
cmp(ary1, ary2);
|
||||
brx(Assembler::equal, true, Assembler::pn, Ldone);
|
||||
delayed()->mov(1, result); // equal
|
||||
|
||||
br_null(ary1, true, Assembler::pn, Ldone);
|
||||
delayed()->clr(result); // not equal
|
||||
|
||||
br_null(ary2, true, Assembler::pn, Ldone);
|
||||
delayed()->clr(result); // not equal
|
||||
|
||||
// load the lengths of arrays
|
||||
ld(Address(ary1, length_offset), limit);
|
||||
ld(Address(ary2, length_offset), tmp);
|
||||
|
||||
// return false if the two arrays are not equal length
|
||||
cmp(limit, tmp);
|
||||
br(Assembler::notEqual, true, Assembler::pn, Ldone);
|
||||
delayed()->clr(result); // not equal
|
||||
}
|
||||
|
||||
cmp_zero_and_br(Assembler::zero, limit, Ldone, true, Assembler::pn);
|
||||
delayed()->mov(1, result); // zero-length arrays are equal
|
||||
|
||||
if (is_array_equ) {
|
||||
// load array addresses
|
||||
add(ary1, base_offset, ary1);
|
||||
add(ary2, base_offset, ary2);
|
||||
// set byte count
|
||||
if (!is_byte) {
|
||||
sll(limit, exact_log2(sizeof(jchar)), limit);
|
||||
}
|
||||
} else {
|
||||
// We have no guarantee that on 64 bit the higher half of limit is 0
|
||||
signx(limit);
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
// Sanity check for doubleword (8-byte) alignment of ary1 and ary2.
|
||||
// Guaranteed on 64-bit systems (see arrayOopDesc::header_size_in_bytes()).
|
||||
Label Laligned;
|
||||
or3(ary1, ary2, tmp);
|
||||
andcc(tmp, 7, tmp);
|
||||
br_null_short(tmp, Assembler::pn, Laligned);
|
||||
STOP("First array element is not 8-byte aligned.");
|
||||
should_not_reach_here();
|
||||
bind(Laligned);
|
||||
#endif
|
||||
|
||||
// Shift ary1 and ary2 to the end of the arrays, negate limit
|
||||
add(ary1, limit, ary1);
|
||||
add(ary2, limit, ary2);
|
||||
neg(limit, limit);
|
||||
|
||||
// MAIN LOOP
|
||||
// Load and compare array elements of size 'byte_width' until the elements are not
|
||||
// equal or we reached the end of the arrays. If the size of the arrays is not a
|
||||
// multiple of 'byte_width', we simply read over the end of the array, bail out and
|
||||
// compare the remaining bytes below by skipping the garbage bytes.
|
||||
ldx(ary1, limit, result);
|
||||
bind(Lloop);
|
||||
ldx(ary2, limit, tmp);
|
||||
inccc(limit, 8);
|
||||
// Bail out if we reached the end (but still do the comparison)
|
||||
br(Assembler::positive, false, Assembler::pn, Lremaining);
|
||||
delayed()->cmp(result, tmp);
|
||||
// Check equality of elements
|
||||
brx(Assembler::equal, false, Assembler::pt, target(Lloop));
|
||||
delayed()->ldx(ary1, limit, result);
|
||||
|
||||
ba(Ldone);
|
||||
delayed()->clr(result); // not equal
|
||||
|
||||
// TAIL COMPARISON
|
||||
// We got here because we reached the end of the arrays. 'limit' is the number of
|
||||
// garbage bytes we may have compared by reading over the end of the arrays. Shift
|
||||
// out the garbage and compare the remaining elements.
|
||||
bind(Lremaining);
|
||||
// Optimistic shortcut: elements potentially including garbage are equal
|
||||
brx(Assembler::equal, true, Assembler::pt, target(Ldone));
|
||||
delayed()->mov(1, result); // equal
|
||||
// Shift 'limit' bytes to the right and compare
|
||||
sll(limit, 3, limit); // bytes to bits
|
||||
srlx(result, limit, result);
|
||||
srlx(tmp, limit, tmp);
|
||||
cmp(result, tmp);
|
||||
clr(result);
|
||||
movcc(Assembler::equal, false, xcc, 1, result);
|
||||
|
||||
bind(Ldone);
|
||||
}
|
||||
|
||||
void MacroAssembler::has_negatives(Register inp, Register size, Register result, Register t2, Register t3, Register t4, Register t5) {
|
||||
|
||||
// test for negative bytes in input string of a given size
|
||||
// result 1 if found, 0 otherwise.
|
||||
|
||||
Label Lcore, Ltail, Lreturn, Lcore_rpt;
|
||||
|
||||
assert_different_registers(inp, size, t2, t3, t4, t5, result);
|
||||
|
||||
Register i = result; // result used as integer index i until very end
|
||||
Register lmask = t2; // t2 is aliased to lmask
|
||||
|
||||
// INITIALIZATION
|
||||
// ===========================================================
|
||||
// initialize highbits mask -> lmask = 0x8080808080808080 (8B/64b)
|
||||
// compute unaligned offset -> i
|
||||
// compute core end index -> t5
|
||||
Assembler::sethi(0x80808000, t2); //! sethi macro fails to emit optimal
|
||||
add(t2, 0x80, t2);
|
||||
sllx(t2, 32, t3);
|
||||
or3(t3, t2, lmask); // 0x8080808080808080 -> lmask
|
||||
sra(size,0,size);
|
||||
andcc(inp, 0x7, i); // unaligned offset -> i
|
||||
br(Assembler::zero, true, Assembler::pn, Lcore); // starts 8B aligned?
|
||||
delayed()->add(size, -8, t5); // (annuled) core end index -> t5
|
||||
|
||||
// ===========================================================
|
||||
|
||||
// UNALIGNED HEAD
|
||||
// ===========================================================
|
||||
// * unaligned head handling: grab aligned 8B containing unaligned inp(ut)
|
||||
// * obliterate (ignore) bytes outside string by shifting off reg ends
|
||||
// * compare with bitmask, short circuit return true if one or more high
|
||||
// bits set.
|
||||
cmp(size, 0);
|
||||
br(Assembler::zero, true, Assembler::pn, Lreturn); // short-circuit?
|
||||
delayed()->mov(0,result); // annuled so i not clobbered for following
|
||||
neg(i, t4);
|
||||
add(i, size, t5);
|
||||
ldx(inp, t4, t3); // raw aligned 8B containing unaligned head -> t3
|
||||
mov(8, t4);
|
||||
sub(t4, t5, t4);
|
||||
sra(t4, 31, t5);
|
||||
andn(t4, t5, t5);
|
||||
add(i, t5, t4);
|
||||
sll(t5, 3, t5);
|
||||
sll(t4, 3, t4); // # bits to shift right, left -> t5,t4
|
||||
srlx(t3, t5, t3);
|
||||
sllx(t3, t4, t3); // bytes outside string in 8B header obliterated -> t3
|
||||
andcc(lmask, t3, G0);
|
||||
brx(Assembler::notZero, true, Assembler::pn, Lreturn); // short circuit?
|
||||
delayed()->mov(1,result); // annuled so i not clobbered for following
|
||||
add(size, -8, t5); // core end index -> t5
|
||||
mov(8, t4);
|
||||
sub(t4, i, i); // # bytes examined in unalgn head (<8) -> i
|
||||
// ===========================================================
|
||||
|
||||
// ALIGNED CORE
|
||||
// ===========================================================
|
||||
// * iterate index i over aligned 8B sections of core, comparing with
|
||||
// bitmask, short circuit return true if one or more high bits set
|
||||
// t5 contains core end index/loop limit which is the index
|
||||
// of the MSB of last (unaligned) 8B fully contained in the string.
|
||||
// inp contains address of first byte in string/array
|
||||
// lmask contains 8B high bit mask for comparison
|
||||
// i contains next index to be processed (adr. inp+i is on 8B boundary)
|
||||
bind(Lcore);
|
||||
cmp_and_br_short(i, t5, Assembler::greater, Assembler::pn, Ltail);
|
||||
bind(Lcore_rpt);
|
||||
ldx(inp, i, t3);
|
||||
andcc(t3, lmask, G0);
|
||||
brx(Assembler::notZero, true, Assembler::pn, Lreturn);
|
||||
delayed()->mov(1, result); // annuled so i not clobbered for following
|
||||
add(i, 8, i);
|
||||
cmp_and_br_short(i, t5, Assembler::lessEqual, Assembler::pn, Lcore_rpt);
|
||||
// ===========================================================
|
||||
|
||||
// ALIGNED TAIL (<8B)
|
||||
// ===========================================================
|
||||
// handle aligned tail of 7B or less as complete 8B, obliterating end of
|
||||
// string bytes by shifting them off end, compare what's left with bitmask
|
||||
// inp contains address of first byte in string/array
|
||||
// lmask contains 8B high bit mask for comparison
|
||||
// i contains next index to be processed (adr. inp+i is on 8B boundary)
|
||||
bind(Ltail);
|
||||
subcc(size, i, t4); // # of remaining bytes in string -> t4
|
||||
// return 0 if no more remaining bytes
|
||||
br(Assembler::lessEqual, true, Assembler::pn, Lreturn);
|
||||
delayed()->mov(0, result); // annuled so i not clobbered for following
|
||||
ldx(inp, i, t3); // load final 8B (aligned) containing tail -> t3
|
||||
mov(8, t5);
|
||||
sub(t5, t4, t4);
|
||||
mov(0, result); // ** i clobbered at this point
|
||||
sll(t4, 3, t4); // bits beyond end of string -> t4
|
||||
srlx(t3, t4, t3); // bytes beyond end now obliterated -> t3
|
||||
andcc(lmask, t3, G0);
|
||||
movcc(Assembler::notZero, false, xcc, 1, result);
|
||||
bind(Lreturn);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// 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_blk_zeroing(), "only works with BIS zeroing");
|
||||
|
@ -1301,36 +1301,6 @@ public:
|
||||
void inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2);
|
||||
void inc_counter(int* counter_addr, Register Rtmp1, Register Rtmp2);
|
||||
|
||||
#ifdef COMPILER2
|
||||
// Compress char[] to byte[] by compressing 16 bytes at once. Return 0 on failure.
|
||||
void string_compress_16(Register src, Register dst, Register cnt, Register result,
|
||||
Register tmp1, Register tmp2, Register tmp3, Register tmp4,
|
||||
FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, Label& Ldone);
|
||||
|
||||
// Compress char[] to byte[]. Return 0 on failure.
|
||||
void string_compress(Register src, Register dst, Register cnt, Register tmp, Register result, Label& Ldone);
|
||||
|
||||
// Inflate byte[] to char[] by inflating 16 bytes at once.
|
||||
void string_inflate_16(Register src, Register dst, Register cnt, Register tmp,
|
||||
FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, FloatRegister ftmp4, Label& Ldone);
|
||||
|
||||
// Inflate byte[] to char[].
|
||||
void string_inflate(Register src, Register dst, Register cnt, Register tmp, Label& Ldone);
|
||||
|
||||
void string_compare(Register str1, Register str2,
|
||||
Register cnt1, Register cnt2,
|
||||
Register tmp1, Register tmp2,
|
||||
Register result, int ae);
|
||||
|
||||
void array_equals(bool is_array_equ, Register ary1, Register ary2,
|
||||
Register limit, Register tmp, Register result, bool is_byte);
|
||||
// test for negative bytes in input string of a given size, result 0 if none
|
||||
void has_negatives(Register inp, Register size, Register result,
|
||||
Register t2, Register t3, Register t4,
|
||||
Register t5);
|
||||
|
||||
#endif
|
||||
|
||||
// Use BIS for zeroing
|
||||
void bis_zeroing(Register to, Register count, Register temp, Label& Ldone);
|
||||
|
||||
|
@ -3086,7 +3086,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
|
||||
__ set_last_Java_frame(SP, noreg);
|
||||
|
||||
Register saved_O7 = O7->after_save();
|
||||
if (!cause_return && SafepointMechanism::uses_thread_local_poll()) {
|
||||
if (!cause_return) {
|
||||
// Keep a copy of the return pc in L0 to detect if it gets modified
|
||||
__ mov(saved_O7, L0);
|
||||
// Adjust and keep a copy of our npc saved by the signal handler
|
||||
@ -3117,7 +3117,7 @@ SafepointBlob* SharedRuntime::generate_handler_blob(address call_ptr, int poll_t
|
||||
__ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), O1);
|
||||
__ br_notnull_short(O1, Assembler::pn, pending);
|
||||
|
||||
if (!cause_return && SafepointMechanism::uses_thread_local_poll()) {
|
||||
if (!cause_return) {
|
||||
// If nobody modified our return pc then we must return to the npc which he saved in L1
|
||||
__ cmp(saved_O7, L0);
|
||||
__ movcc(Assembler::equal, false, Assembler::ptr_cc, L1, saved_O7);
|
||||
|
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -471,6 +471,13 @@ class HandlerImpl {
|
||||
}
|
||||
};
|
||||
|
||||
class Node::PD {
|
||||
public:
|
||||
enum NodeFlags {
|
||||
_last_flag = Node::_last_flag
|
||||
};
|
||||
};
|
||||
|
||||
%}
|
||||
|
||||
source %{
|
||||
@ -483,6 +490,17 @@ static FloatRegister reg_to_SingleFloatRegister_object(int register_encoding);
|
||||
static FloatRegister reg_to_DoubleFloatRegister_object(int register_encoding);
|
||||
static Register reg_to_register_object(int register_encoding);
|
||||
|
||||
void PhaseOutput::pd_perform_mach_node_analysis() {
|
||||
}
|
||||
|
||||
int MachNode::pd_alignment_required() const {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int MachNode::compute_padding(int current_offset) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Used by the DFA in dfa_sparc.cpp.
|
||||
// Check for being able to use a V9 branch-on-register. Requires a
|
||||
// compare-vs-zero, equal/not-equal, of a value which was zero- or sign-
|
||||
@ -592,7 +610,7 @@ bool SafePointNode::needs_polling_address_input() {
|
||||
|
||||
// emit an interrupt that is caught by the debugger (for debugging compiler)
|
||||
void emit_break(CodeBuffer &cbuf) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ breakpoint_trap();
|
||||
}
|
||||
|
||||
@ -612,7 +630,7 @@ uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const {
|
||||
|
||||
// Traceable jump
|
||||
void emit_jmpl(CodeBuffer &cbuf, int jump_target) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register rdest = reg_to_register_object(jump_target);
|
||||
__ JMP(rdest, 0);
|
||||
__ delayed()->nop();
|
||||
@ -620,19 +638,19 @@ void emit_jmpl(CodeBuffer &cbuf, int jump_target) {
|
||||
|
||||
// Traceable jump and set exception pc
|
||||
void emit_jmpl_set_exception_pc(CodeBuffer &cbuf, int jump_target) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register rdest = reg_to_register_object(jump_target);
|
||||
__ JMP(rdest, 0);
|
||||
__ delayed()->add(O7, frame::pc_return_offset, Oissuing_pc );
|
||||
}
|
||||
|
||||
void emit_nop(CodeBuffer &cbuf) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ nop();
|
||||
}
|
||||
|
||||
void emit_illtrap(CodeBuffer &cbuf) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ illtrap(0);
|
||||
}
|
||||
|
||||
@ -908,7 +926,7 @@ void emit_form3_mem_reg(CodeBuffer &cbuf, PhaseRegAlloc* ra, const MachNode* n,
|
||||
disp += STACK_BIAS;
|
||||
// Check that stack offset fits, load into O7 if not
|
||||
if (!Assembler::is_simm13(disp)) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ set(disp, O7);
|
||||
if (index != R_G0_enc) {
|
||||
__ add(O7, reg_to_register_object(index), O7);
|
||||
@ -932,7 +950,7 @@ void emit_form3_mem_reg(CodeBuffer &cbuf, PhaseRegAlloc* ra, const MachNode* n,
|
||||
|
||||
#ifdef ASSERT
|
||||
if (VerifyOops) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
if (is_verified_oop_base) {
|
||||
__ verify_oop(reg_to_register_object(src1_enc));
|
||||
}
|
||||
@ -960,7 +978,7 @@ void emit_call_reloc(CodeBuffer &cbuf, intptr_t entry_point, RelocationHolder co
|
||||
// putting the "mov" instruction in the delay slot but the problem
|
||||
// may bite us again at some other point and a cleaner/generic
|
||||
// solution using relocations would be needed.
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ set_inst_mark();
|
||||
|
||||
// We flush the current window just so that there is a valid stack copy
|
||||
@ -1024,7 +1042,7 @@ void MachConstantBaseNode::postalloc_expand(GrowableArray <Node *> *nodes, Phase
|
||||
void MachConstantBaseNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const {
|
||||
Compile* C = ra_->C;
|
||||
ConstantTable& constant_table = C->output()->constant_table();
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
Register r = as_Register(ra_->get_encode(this));
|
||||
CodeSection* consts_section = __ code()->consts();
|
||||
@ -1153,7 +1171,7 @@ void MachPrologNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
|
||||
|
||||
void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
Compile* C = ra_->C;
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
for (int i = 0; i < OptoPrologueNops; i++) {
|
||||
__ nop();
|
||||
@ -1206,11 +1224,7 @@ void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
|
||||
Compile* C = ra_->C;
|
||||
|
||||
if(do_polling() && ra_->C->is_method_compilation()) {
|
||||
if (SafepointMechanism::uses_global_page_poll()) {
|
||||
st->print("SETHI #PollAddr,L0\t! Load Polling address\n\t");
|
||||
} else {
|
||||
st->print("LDX [R_G2 + #poll_offset],L0\t! Load local polling address\n\t");
|
||||
}
|
||||
st->print("LDX [R_G2 + #poll_offset],L0\t! Load local polling address\n\t");
|
||||
st->print("LDX [L0],G0\t!Poll for Safepointing\n\t");
|
||||
}
|
||||
|
||||
@ -1226,7 +1240,7 @@ void MachEpilogNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
|
||||
#endif
|
||||
|
||||
void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Compile* C = ra_->C;
|
||||
|
||||
__ verify_thread();
|
||||
@ -1237,12 +1251,7 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
|
||||
// If this does safepoint polling, then do it here
|
||||
if(do_polling() && ra_->C->is_method_compilation()) {
|
||||
if (SafepointMechanism::uses_thread_local_poll()) {
|
||||
__ ld_ptr(Address(G2_thread, Thread::polling_page_offset()), L0);
|
||||
} else {
|
||||
AddressLiteral polling_page(os::get_polling_page());
|
||||
__ sethi(polling_page, L0);
|
||||
}
|
||||
__ ld_ptr(Address(G2_thread, Thread::polling_page_offset()), L0);
|
||||
__ relocate(relocInfo::poll_return_type);
|
||||
__ ld_ptr(L0, 0, G0);
|
||||
}
|
||||
@ -1273,12 +1282,6 @@ const Pipeline * MachEpilogNode::pipeline() const {
|
||||
return MachNode::pipeline_class();
|
||||
}
|
||||
|
||||
int MachEpilogNode::safepoint_offset() const {
|
||||
assert(SafepointMechanism::uses_global_page_poll(), "sanity");
|
||||
assert( do_polling(), "no return for this epilog node");
|
||||
return MacroAssembler::insts_for_sethi(os::get_polling_page()) * BytesPerInstWord;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
// Figure out which register class each belongs in: rc_int, rc_float, rc_stack
|
||||
@ -1534,7 +1537,7 @@ void MachNopNode::format(PhaseRegAlloc *, outputStream *st) const {
|
||||
#endif
|
||||
|
||||
void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
for (int i = 0; i < _count; i += 1) {
|
||||
__ nop();
|
||||
}
|
||||
@ -1555,7 +1558,7 @@ void BoxLockNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
|
||||
#endif
|
||||
|
||||
void BoxLockNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int offset = ra_->reg2offset(in_RegMask(0).find_first_elem()) + STACK_BIAS;
|
||||
int reg = ra_->get_encode(this);
|
||||
|
||||
@ -1599,7 +1602,7 @@ void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const {
|
||||
#endif
|
||||
|
||||
void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register G5_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode());
|
||||
Register temp_reg = G3;
|
||||
assert( G5_ic_reg != temp_reg, "conflicting registers" );
|
||||
@ -1624,7 +1627,7 @@ uint MachUEPNode::size(PhaseRegAlloc *ra_) const {
|
||||
int HandlerImpl::emit_exception_handler(CodeBuffer& cbuf) {
|
||||
Register temp_reg = G3;
|
||||
AddressLiteral exception_blob(OptoRuntime::exception_blob()->entry_point());
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
address base = __ start_a_stub(size_exception_handler());
|
||||
if (base == NULL) {
|
||||
@ -1649,7 +1652,7 @@ int HandlerImpl::emit_deopt_handler(CodeBuffer& cbuf) {
|
||||
// at a poll and everything (including G3) can be live.
|
||||
Register temp_reg = L0;
|
||||
AddressLiteral deopt_blob(SharedRuntime::deopt_blob()->unpack());
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
address base = __ start_a_stub(size_deopt_handler());
|
||||
if (base == NULL) {
|
||||
@ -1959,10 +1962,15 @@ const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||
|
||||
const bool Matcher::convi2l_type_required = true;
|
||||
|
||||
// Should the matcher clone input 'm' of node 'n'?
|
||||
bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Should the Matcher clone shifts on addressing modes, expecting them
|
||||
// to be subsumed into complex addressing expressions or compute them
|
||||
// into registers?
|
||||
bool Matcher::clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
|
||||
bool Matcher::pd_clone_address_expressions(AddPNode* m, Matcher::MStack& mstack, VectorSet& address_visited) {
|
||||
return clone_base_plus_offset_address(m, mstack, address_visited);
|
||||
}
|
||||
|
||||
@ -2007,7 +2015,7 @@ void Compile::reshape_address(AddPNode* addp) {
|
||||
encode %{
|
||||
enc_class enc_untested %{
|
||||
#ifdef ASSERT
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ untested("encoding");
|
||||
#endif
|
||||
%}
|
||||
@ -2142,7 +2150,7 @@ encode %{
|
||||
|
||||
/* %%% merge with enc_to_bool */
|
||||
enc_class enc_convP2B( iRegI dst, iRegP src ) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
Register src_reg = reg_to_register_object($src$$reg);
|
||||
Register dst_reg = reg_to_register_object($dst$$reg);
|
||||
@ -2151,7 +2159,7 @@ encode %{
|
||||
|
||||
enc_class enc_cadd_cmpLTMask( iRegI p, iRegI q, iRegI y, iRegI tmp ) %{
|
||||
// (Set p (AddI (AndI (CmpLTMask p q) y) (SubI p q)))
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
Register p_reg = reg_to_register_object($p$$reg);
|
||||
Register q_reg = reg_to_register_object($q$$reg);
|
||||
@ -2284,13 +2292,13 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class enc_PartialSubtypeCheck() %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ call(StubRoutines::Sparc::partial_subtype_check(), relocInfo::runtime_call_type);
|
||||
__ delayed()->nop();
|
||||
%}
|
||||
|
||||
enc_class enc_bp( label labl, cmpOp cmp, flagsReg cc ) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label* L = $labl$$label;
|
||||
Assembler::Predict predict_taken =
|
||||
cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
|
||||
@ -2300,7 +2308,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class enc_bpr( label labl, cmpOp_reg cmp, iRegI op1 ) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Label* L = $labl$$label;
|
||||
Assembler::Predict predict_taken =
|
||||
cbuf.is_backward_branch(*L) ? Assembler::pt : Assembler::pn;
|
||||
@ -2419,13 +2427,13 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class Set32( immI src, iRegI rd ) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ set($src$$constant, reg_to_register_object($rd$$reg));
|
||||
%}
|
||||
|
||||
enc_class call_epilog %{
|
||||
if( VerifyStackAtCalls ) {
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
int framesize = ra_->C->output()->frame_size_in_bytes();
|
||||
Register temp_reg = G3;
|
||||
__ add(SP, framesize, temp_reg);
|
||||
@ -2447,12 +2455,12 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class preserve_SP %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ mov(SP, L7_mh_SP_save);
|
||||
%}
|
||||
|
||||
enc_class restore_SP %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ mov(L7_mh_SP_save, SP);
|
||||
%}
|
||||
|
||||
@ -2477,7 +2485,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class Java_Dynamic_Call (method meth) %{ // JAVA DYNAMIC CALL
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ set_inst_mark();
|
||||
int vtable_index = this->_vtable_index;
|
||||
// MachCallDynamicJavaNode::ret_addr_offset uses this same test
|
||||
@ -2526,7 +2534,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class Java_Compiled_Call (method meth) %{ // JAVA COMPILED CALL
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
Register G5_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode());
|
||||
Register temp_reg = G3; // caller must kill G3! We cannot reuse G5_ic_reg here because
|
||||
@ -2543,7 +2551,7 @@ encode %{
|
||||
%}
|
||||
|
||||
enc_class idiv_reg(iRegIsafe src1, iRegIsafe src2, iRegIsafe dst) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register Rdividend = reg_to_register_object($src1$$reg);
|
||||
Register Rdivisor = reg_to_register_object($src2$$reg);
|
||||
Register Rresult = reg_to_register_object($dst$$reg);
|
||||
@ -2554,7 +2562,7 @@ enc_class idiv_reg(iRegIsafe src1, iRegIsafe src2, iRegIsafe dst) %{
|
||||
%}
|
||||
|
||||
enc_class idiv_imm(iRegIsafe src1, immI13 imm, iRegIsafe dst) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
Register Rdividend = reg_to_register_object($src1$$reg);
|
||||
int divisor = $imm$$constant;
|
||||
@ -2565,7 +2573,7 @@ enc_class idiv_imm(iRegIsafe src1, immI13 imm, iRegIsafe dst) %{
|
||||
%}
|
||||
|
||||
enc_class enc_mul_hi(iRegIsafe dst, iRegIsafe src1, iRegIsafe src2) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register Rsrc1 = reg_to_register_object($src1$$reg);
|
||||
Register Rsrc2 = reg_to_register_object($src2$$reg);
|
||||
Register Rdst = reg_to_register_object($dst$$reg);
|
||||
@ -2577,7 +2585,7 @@ enc_class enc_mul_hi(iRegIsafe dst, iRegIsafe src1, iRegIsafe src2) %{
|
||||
%}
|
||||
|
||||
enc_class irem_reg(iRegIsafe src1, iRegIsafe src2, iRegIsafe dst, o7RegL scratch) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register Rdividend = reg_to_register_object($src1$$reg);
|
||||
Register Rdivisor = reg_to_register_object($src2$$reg);
|
||||
Register Rresult = reg_to_register_object($dst$$reg);
|
||||
@ -2594,7 +2602,7 @@ enc_class irem_reg(iRegIsafe src1, iRegIsafe src2, iRegIsafe dst, o7RegL scratch
|
||||
%}
|
||||
|
||||
enc_class irem_imm(iRegIsafe src1, immI13 imm, iRegIsafe dst, o7RegL scratch) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
Register Rdividend = reg_to_register_object($src1$$reg);
|
||||
int divisor = $imm$$constant;
|
||||
@ -2610,7 +2618,7 @@ enc_class irem_imm(iRegIsafe src1, immI13 imm, iRegIsafe dst, o7RegL scratch) %{
|
||||
%}
|
||||
|
||||
enc_class fabss (sflt_reg dst, sflt_reg src) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Fdst = reg_to_SingleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fsrc = reg_to_SingleFloatRegister_object($src$$reg);
|
||||
@ -2619,7 +2627,7 @@ enc_class fabss (sflt_reg dst, sflt_reg src) %{
|
||||
%}
|
||||
|
||||
enc_class fabsd (dflt_reg dst, dflt_reg src) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Fdst = reg_to_DoubleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fsrc = reg_to_DoubleFloatRegister_object($src$$reg);
|
||||
@ -2628,7 +2636,7 @@ enc_class fabsd (dflt_reg dst, dflt_reg src) %{
|
||||
%}
|
||||
|
||||
enc_class fnegd (dflt_reg dst, dflt_reg src) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Fdst = reg_to_DoubleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fsrc = reg_to_DoubleFloatRegister_object($src$$reg);
|
||||
@ -2637,7 +2645,7 @@ enc_class fnegd (dflt_reg dst, dflt_reg src) %{
|
||||
%}
|
||||
|
||||
enc_class fsqrts (sflt_reg dst, sflt_reg src) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Fdst = reg_to_SingleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fsrc = reg_to_SingleFloatRegister_object($src$$reg);
|
||||
@ -2646,7 +2654,7 @@ enc_class fsqrts (sflt_reg dst, sflt_reg src) %{
|
||||
%}
|
||||
|
||||
enc_class fsqrtd (dflt_reg dst, dflt_reg src) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Fdst = reg_to_DoubleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fsrc = reg_to_DoubleFloatRegister_object($src$$reg);
|
||||
@ -2656,7 +2664,7 @@ enc_class fsqrtd (dflt_reg dst, dflt_reg src) %{
|
||||
|
||||
|
||||
enc_class fmadds (sflt_reg dst, sflt_reg a, sflt_reg b, sflt_reg c) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Frd = reg_to_SingleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fra = reg_to_SingleFloatRegister_object($a$$reg);
|
||||
@ -2667,7 +2675,7 @@ enc_class fmadds (sflt_reg dst, sflt_reg a, sflt_reg b, sflt_reg c) %{
|
||||
%}
|
||||
|
||||
enc_class fmaddd (dflt_reg dst, dflt_reg a, dflt_reg b, dflt_reg c) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Frd = reg_to_DoubleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fra = reg_to_DoubleFloatRegister_object($a$$reg);
|
||||
@ -2678,7 +2686,7 @@ enc_class fmaddd (dflt_reg dst, dflt_reg a, dflt_reg b, dflt_reg c) %{
|
||||
%}
|
||||
|
||||
enc_class fmsubs (sflt_reg dst, sflt_reg a, sflt_reg b, sflt_reg c) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Frd = reg_to_SingleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fra = reg_to_SingleFloatRegister_object($a$$reg);
|
||||
@ -2689,7 +2697,7 @@ enc_class fmsubs (sflt_reg dst, sflt_reg a, sflt_reg b, sflt_reg c) %{
|
||||
%}
|
||||
|
||||
enc_class fmsubd (dflt_reg dst, dflt_reg a, dflt_reg b, dflt_reg c) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Frd = reg_to_DoubleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fra = reg_to_DoubleFloatRegister_object($a$$reg);
|
||||
@ -2700,7 +2708,7 @@ enc_class fmsubd (dflt_reg dst, dflt_reg a, dflt_reg b, dflt_reg c) %{
|
||||
%}
|
||||
|
||||
enc_class fnmadds (sflt_reg dst, sflt_reg a, sflt_reg b, sflt_reg c) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Frd = reg_to_SingleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fra = reg_to_SingleFloatRegister_object($a$$reg);
|
||||
@ -2711,7 +2719,7 @@ enc_class fnmadds (sflt_reg dst, sflt_reg a, sflt_reg b, sflt_reg c) %{
|
||||
%}
|
||||
|
||||
enc_class fnmaddd (dflt_reg dst, dflt_reg a, dflt_reg b, dflt_reg c) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Frd = reg_to_DoubleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fra = reg_to_DoubleFloatRegister_object($a$$reg);
|
||||
@ -2722,7 +2730,7 @@ enc_class fnmaddd (dflt_reg dst, dflt_reg a, dflt_reg b, dflt_reg c) %{
|
||||
%}
|
||||
|
||||
enc_class fnmsubs (sflt_reg dst, sflt_reg a, sflt_reg b, sflt_reg c) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Frd = reg_to_SingleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fra = reg_to_SingleFloatRegister_object($a$$reg);
|
||||
@ -2733,7 +2741,7 @@ enc_class fnmsubs (sflt_reg dst, sflt_reg a, sflt_reg b, sflt_reg c) %{
|
||||
%}
|
||||
|
||||
enc_class fnmsubd (dflt_reg dst, dflt_reg a, dflt_reg b, dflt_reg c) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Frd = reg_to_DoubleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fra = reg_to_DoubleFloatRegister_object($a$$reg);
|
||||
@ -2745,7 +2753,7 @@ enc_class fnmsubd (dflt_reg dst, dflt_reg a, dflt_reg b, dflt_reg c) %{
|
||||
|
||||
|
||||
enc_class fmovs (dflt_reg dst, dflt_reg src) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Fdst = reg_to_SingleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fsrc = reg_to_SingleFloatRegister_object($src$$reg);
|
||||
@ -2754,7 +2762,7 @@ enc_class fmovs (dflt_reg dst, dflt_reg src) %{
|
||||
%}
|
||||
|
||||
enc_class fmovd (dflt_reg dst, dflt_reg src) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
FloatRegister Fdst = reg_to_DoubleFloatRegister_object($dst$$reg);
|
||||
FloatRegister Fsrc = reg_to_DoubleFloatRegister_object($src$$reg);
|
||||
@ -2763,7 +2771,7 @@ enc_class fmovd (dflt_reg dst, dflt_reg src) %{
|
||||
%}
|
||||
|
||||
enc_class Fast_Lock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
Register Roop = reg_to_register_object($oop$$reg);
|
||||
Register Rbox = reg_to_register_object($box$$reg);
|
||||
@ -2779,7 +2787,7 @@ enc_class Fast_Lock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
%}
|
||||
|
||||
enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
|
||||
Register Roop = reg_to_register_object($oop$$reg);
|
||||
Register Rbox = reg_to_register_object($box$$reg);
|
||||
@ -2795,7 +2803,7 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
%}
|
||||
|
||||
enc_class enc_cas( iRegP mem, iRegP old, iRegP new ) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register Rmem = reg_to_register_object($mem$$reg);
|
||||
Register Rold = reg_to_register_object($old$$reg);
|
||||
Register Rnew = reg_to_register_object($new$$reg);
|
||||
@ -2809,7 +2817,7 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
Register Rold = reg_to_register_object($old$$reg);
|
||||
Register Rnew = reg_to_register_object($new$$reg);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ mov(Rnew, O7);
|
||||
__ casx(Rmem, Rold, O7);
|
||||
__ cmp( Rold, O7 );
|
||||
@ -2821,7 +2829,7 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
Register Rold = reg_to_register_object($old$$reg);
|
||||
Register Rnew = reg_to_register_object($new$$reg);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ mov(Rnew, O7);
|
||||
__ cas(Rmem, Rold, O7);
|
||||
__ cmp( Rold, O7 );
|
||||
@ -2833,7 +2841,7 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
Register Rold = reg_to_register_object($old$$reg);
|
||||
Register Rnew = reg_to_register_object($new$$reg);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ cas(Rmem, Rold, Rnew);
|
||||
%}
|
||||
|
||||
@ -2843,14 +2851,14 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
Register Rold = reg_to_register_object($old$$reg);
|
||||
Register Rnew = reg_to_register_object($new$$reg);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ casx(Rmem, Rold, Rnew);
|
||||
%}
|
||||
|
||||
enc_class enc_lflags_ne_to_boolean( iRegI res ) %{
|
||||
Register Rres = reg_to_register_object($res$$reg);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ mov(1, Rres);
|
||||
__ movcc( Assembler::notEqual, false, Assembler::xcc, G0, Rres );
|
||||
%}
|
||||
@ -2858,13 +2866,13 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
enc_class enc_iflags_ne_to_boolean( iRegI res ) %{
|
||||
Register Rres = reg_to_register_object($res$$reg);
|
||||
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ mov(1, Rres);
|
||||
__ movcc( Assembler::notEqual, false, Assembler::icc, G0, Rres );
|
||||
%}
|
||||
|
||||
enc_class floating_cmp ( iRegP dst, regF src1, regF src2 ) %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
Register Rdst = reg_to_register_object($dst$$reg);
|
||||
FloatRegister Fsrc1 = $primary ? reg_to_SingleFloatRegister_object($src1$$reg)
|
||||
: reg_to_DoubleFloatRegister_object($src1$$reg);
|
||||
@ -2880,7 +2888,7 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
Register temp_reg = G3;
|
||||
AddressLiteral rethrow_stub(OptoRuntime::rethrow_stub());
|
||||
assert(temp_reg != reg_to_register_object(R_I0_num), "temp must not break oop_reg");
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
#ifdef ASSERT
|
||||
__ save_frame(0);
|
||||
AddressLiteral last_rethrow_addrlit(&last_rethrow);
|
||||
@ -2911,17 +2919,17 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||
%}
|
||||
|
||||
enc_class enc_membar_acquire %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ membar( Assembler::Membar_mask_bits(Assembler::LoadStore | Assembler::LoadLoad) );
|
||||
%}
|
||||
|
||||
enc_class enc_membar_release %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ membar( Assembler::Membar_mask_bits(Assembler::LoadStore | Assembler::StoreStore) );
|
||||
%}
|
||||
|
||||
enc_class enc_membar_volatile %{
|
||||
MacroAssembler _masm(&cbuf);
|
||||
C2_MacroAssembler _masm(&cbuf);
|
||||
__ membar( Assembler::Membar_mask_bits(Assembler::StoreLoad) );
|
||||
%}
|
||||
|
||||
@ -3375,15 +3383,6 @@ operand immP0() %{
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
operand immP_poll() %{
|
||||
predicate(n->get_ptr() != 0 && n->get_ptr() == (intptr_t)os::get_polling_page());
|
||||
match(ConP);
|
||||
|
||||
// formats are generated automatically for constants and base registers
|
||||
format %{ %}
|
||||
interface(CONST_INTER);
|
||||
%}
|
||||
|
||||
// Pointer Immediate
|
||||
operand immN()
|
||||
%{
|
||||
@ -4492,12 +4491,6 @@ pipe_class loadConP( iRegP dst, immP src ) %{
|
||||
fixed_latency(6);
|
||||
%}
|
||||
|
||||
// Polling Address
|
||||
pipe_class loadConP_poll( iRegP dst, immP_poll src ) %{
|
||||
instruction_count(0); multiple_bundles;
|
||||
fixed_latency(6);
|
||||
%}
|
||||
|
||||
// Long Constant small
|
||||
pipe_class loadConLlo( iRegL dst, immL src ) %{
|
||||
instruction_count(2);
|
||||
@ -5883,17 +5876,6 @@ instruct loadConP0(iRegP dst, immP0 src) %{
|
||||
ins_pipe(ialu_imm);
|
||||
%}
|
||||
|
||||
instruct loadConP_poll(iRegP dst, immP_poll src) %{
|
||||
match(Set dst src);
|
||||
ins_cost(DEFAULT_COST);
|
||||
format %{ "SET $src,$dst\t!ptr" %}
|
||||
ins_encode %{
|
||||
AddressLiteral polling_page(os::get_polling_page());
|
||||
__ sethi(polling_page, reg_to_register_object($dst$$reg));
|
||||
%}
|
||||
ins_pipe(loadConP_poll);
|
||||
%}
|
||||
|
||||
instruct loadConN0(iRegN dst, immN0 src) %{
|
||||
match(Set dst src);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -2025,7 +2025,7 @@ void TemplateTable::_return(TosState state) {
|
||||
__ bind(skip_register_finalizer);
|
||||
}
|
||||
|
||||
if (SafepointMechanism::uses_thread_local_poll() && _desc->bytecode() != Bytecodes::_return_register_finalizer) {
|
||||
if (_desc->bytecode() != Bytecodes::_return_register_finalizer) {
|
||||
Label no_safepoint;
|
||||
__ ldx(Address(G2_thread, Thread::polling_page_offset()), G3_scratch, 0);
|
||||
__ btst(SafepointMechanism::poll_bit(), G3_scratch);
|
||||
|
@ -470,97 +470,143 @@ bool Assembler::emit_compressed_disp_byte(int &disp) {
|
||||
return is8bit(disp);
|
||||
}
|
||||
|
||||
static bool is_valid_encoding(int reg_enc) {
|
||||
return reg_enc >= 0;
|
||||
}
|
||||
|
||||
void Assembler::emit_operand(Register reg, Register base, Register index,
|
||||
Address::ScaleFactor scale, int disp,
|
||||
RelocationHolder const& rspec,
|
||||
int rip_relative_correction) {
|
||||
static int raw_encode(Register reg) {
|
||||
assert(reg == noreg || reg->is_valid(), "sanity");
|
||||
int reg_enc = (intptr_t)reg;
|
||||
assert(reg_enc == -1 || is_valid_encoding(reg_enc), "sanity");
|
||||
return reg_enc;
|
||||
}
|
||||
|
||||
static int raw_encode(XMMRegister xmmreg) {
|
||||
assert(xmmreg == xnoreg || xmmreg->is_valid(), "sanity");
|
||||
int xmmreg_enc = (intptr_t)xmmreg;
|
||||
assert(xmmreg_enc == -1 || is_valid_encoding(xmmreg_enc), "sanity");
|
||||
return xmmreg_enc;
|
||||
}
|
||||
|
||||
static int modrm_encoding(int mod, int dst_enc, int src_enc) {
|
||||
return (mod & 3) << 6 | (dst_enc & 7) << 3 | (src_enc & 7);
|
||||
}
|
||||
|
||||
static int sib_encoding(Address::ScaleFactor scale, int index_enc, int base_enc) {
|
||||
return (scale & 3) << 6 | (index_enc & 7) << 3 | (base_enc & 7);
|
||||
}
|
||||
|
||||
inline void Assembler::emit_modrm(int mod, int dst_enc, int src_enc) {
|
||||
assert((mod & 3) != 0b11, "forbidden");
|
||||
int modrm = modrm_encoding(mod, dst_enc, src_enc);
|
||||
emit_int8(modrm);
|
||||
}
|
||||
|
||||
inline void Assembler::emit_modrm_disp8(int mod, int dst_enc, int src_enc,
|
||||
int disp) {
|
||||
int modrm = modrm_encoding(mod, dst_enc, src_enc);
|
||||
emit_int16(modrm, disp & 0xFF);
|
||||
}
|
||||
|
||||
inline void Assembler::emit_modrm_sib(int mod, int dst_enc, int src_enc,
|
||||
Address::ScaleFactor scale, int index_enc, int base_enc) {
|
||||
int modrm = modrm_encoding(mod, dst_enc, src_enc);
|
||||
int sib = sib_encoding(scale, index_enc, base_enc);
|
||||
emit_int16(modrm, sib);
|
||||
}
|
||||
|
||||
inline void Assembler::emit_modrm_sib_disp8(int mod, int dst_enc, int src_enc,
|
||||
Address::ScaleFactor scale, int index_enc, int base_enc,
|
||||
int disp) {
|
||||
int modrm = modrm_encoding(mod, dst_enc, src_enc);
|
||||
int sib = sib_encoding(scale, index_enc, base_enc);
|
||||
emit_int24(modrm, sib, disp & 0xFF);
|
||||
}
|
||||
|
||||
void Assembler::emit_operand_helper(int reg_enc, int base_enc, int index_enc,
|
||||
Address::ScaleFactor scale, int disp,
|
||||
RelocationHolder const& rspec,
|
||||
int rip_relative_correction) {
|
||||
bool no_relocation = (rspec.type() == relocInfo::none);
|
||||
|
||||
// Encode the registers as needed in the fields they are used in
|
||||
int regenc = encode(reg) << 3;
|
||||
if (base->is_valid()) {
|
||||
int baseenc = encode(base);
|
||||
if (index->is_valid()) {
|
||||
if (is_valid_encoding(base_enc)) {
|
||||
if (is_valid_encoding(index_enc)) {
|
||||
assert(scale != Address::no_scale, "inconsistent address");
|
||||
// [base + index*scale + disp]
|
||||
int indexenc = encode(index) << 3;
|
||||
if (disp == 0 && no_relocation &&
|
||||
base != rbp LP64_ONLY(&& base != r13)) {
|
||||
base_enc != rbp->encoding() LP64_ONLY(&& base_enc != r13->encoding())) {
|
||||
// [base + index*scale]
|
||||
// [00 reg 100][ss index base]
|
||||
assert(index != rsp, "illegal addressing mode");
|
||||
emit_int16((0x04 | regenc),
|
||||
(scale << 6 | indexenc | baseenc));
|
||||
emit_modrm_sib(0b00, reg_enc, 0b100,
|
||||
scale, index_enc, base_enc);
|
||||
} else if (emit_compressed_disp_byte(disp) && no_relocation) {
|
||||
// [base + index*scale + imm8]
|
||||
// [01 reg 100][ss index base] imm8
|
||||
assert(index != rsp, "illegal addressing mode");
|
||||
emit_int24(0x44 | regenc,
|
||||
scale << 6 | indexenc | baseenc,
|
||||
disp & 0xFF);
|
||||
emit_modrm_sib_disp8(0b01, reg_enc, 0b100,
|
||||
scale, index_enc, base_enc,
|
||||
disp);
|
||||
} else {
|
||||
// [base + index*scale + disp32]
|
||||
// [10 reg 100][ss index base] disp32
|
||||
assert(index != rsp, "illegal addressing mode");
|
||||
emit_int16(0x84 | regenc,
|
||||
scale << 6 | indexenc | baseenc);
|
||||
emit_modrm_sib(0b10, reg_enc, 0b100,
|
||||
scale, index_enc, base_enc);
|
||||
emit_data(disp, rspec, disp32_operand);
|
||||
}
|
||||
} else if (base == rsp LP64_ONLY(|| base == r12)) {
|
||||
} else if (base_enc == rsp->encoding() LP64_ONLY(|| base_enc == r12->encoding())) {
|
||||
// [rsp + disp]
|
||||
if (disp == 0 && no_relocation) {
|
||||
// [rsp]
|
||||
// [00 reg 100][00 100 100]
|
||||
emit_int16(0x04 | regenc,
|
||||
0x24);
|
||||
emit_modrm_sib(0b00, reg_enc, 0b100,
|
||||
Address::times_1, 0b100, 0b100);
|
||||
} else if (emit_compressed_disp_byte(disp) && no_relocation) {
|
||||
// [rsp + imm8]
|
||||
// [01 reg 100][00 100 100] disp8
|
||||
emit_int24(0x44 | regenc,
|
||||
0x24,
|
||||
disp & 0xFF);
|
||||
emit_modrm_sib_disp8(0b01, reg_enc, 0b100,
|
||||
Address::times_1, 0b100, 0b100,
|
||||
disp);
|
||||
} else {
|
||||
// [rsp + imm32]
|
||||
// [10 reg 100][00 100 100] disp32
|
||||
emit_int16(0x84 | regenc,
|
||||
0x24);
|
||||
emit_modrm_sib(0b10, reg_enc, 0b100,
|
||||
Address::times_1, 0b100, 0b100);
|
||||
emit_data(disp, rspec, disp32_operand);
|
||||
}
|
||||
} else {
|
||||
// [base + disp]
|
||||
assert(base != rsp LP64_ONLY(&& base != r12), "illegal addressing mode");
|
||||
assert(base_enc != rsp->encoding() LP64_ONLY(&& base_enc != r12->encoding()), "illegal addressing mode");
|
||||
if (disp == 0 && no_relocation &&
|
||||
base != rbp LP64_ONLY(&& base != r13)) {
|
||||
base_enc != rbp->encoding() LP64_ONLY(&& base_enc != r13->encoding())) {
|
||||
// [base]
|
||||
// [00 reg base]
|
||||
emit_int8(0x00 | regenc | baseenc);
|
||||
emit_modrm(0, reg_enc, base_enc);
|
||||
} else if (emit_compressed_disp_byte(disp) && no_relocation) {
|
||||
// [base + disp8]
|
||||
// [01 reg base] disp8
|
||||
emit_int16(0x40 | regenc | baseenc,
|
||||
disp & 0xFF);
|
||||
emit_modrm_disp8(0b01, reg_enc, base_enc,
|
||||
disp);
|
||||
} else {
|
||||
// [base + disp32]
|
||||
// [10 reg base] disp32
|
||||
emit_int8(0x80 | regenc | baseenc);
|
||||
emit_modrm(0b10, reg_enc, base_enc);
|
||||
emit_data(disp, rspec, disp32_operand);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (index->is_valid()) {
|
||||
if (is_valid_encoding(index_enc)) {
|
||||
assert(scale != Address::no_scale, "inconsistent address");
|
||||
// base == noreg
|
||||
// [index*scale + disp]
|
||||
// [00 reg 100][ss index 101] disp32
|
||||
assert(index != rsp, "illegal addressing mode");
|
||||
emit_int16(0x04 | regenc,
|
||||
scale << 6 | (encode(index) << 3) | 0x05);
|
||||
emit_modrm_sib(0b00, reg_enc, 0b100,
|
||||
scale, index_enc, 0b101 /* no base */);
|
||||
emit_data(disp, rspec, disp32_operand);
|
||||
} else if (!no_relocation) {
|
||||
// base == noreg, index == noreg
|
||||
// [disp] (64bit) RIP-RELATIVE (32bit) abs
|
||||
// [00 000 101] disp32
|
||||
// [00 reg 101] disp32
|
||||
|
||||
emit_int8(0x05 | regenc);
|
||||
emit_modrm(0b00, reg_enc, 0b101 /* no base */);
|
||||
// Note that the RIP-rel. correction applies to the generated
|
||||
// disp field, but _not_ to the target address in the rspec.
|
||||
|
||||
@ -577,45 +623,44 @@ void Assembler::emit_operand(Register reg, Register base, Register index,
|
||||
emit_data((int32_t) adjusted, rspec, disp32_operand);
|
||||
|
||||
} else {
|
||||
// base == noreg, index == noreg, no_relocation == true
|
||||
// 32bit never did this, did everything as the rip-rel/disp code above
|
||||
// [disp] ABSOLUTE
|
||||
// [00 reg 100][00 100 101] disp32
|
||||
emit_int16(0x04 | regenc,
|
||||
0x25);
|
||||
emit_modrm_sib(0b00, reg_enc, 0b100 /* no base */,
|
||||
Address::times_1, 0b100, 0b101);
|
||||
emit_data(disp, rspec, disp32_operand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Assembler::emit_operand(XMMRegister reg, Register base, Register index,
|
||||
void Assembler::emit_operand(Register reg, Register base, Register index,
|
||||
Address::ScaleFactor scale, int disp,
|
||||
RelocationHolder const& rspec,
|
||||
int rip_relative_correction) {
|
||||
assert(!index->is_valid() || index != rsp, "illegal addressing mode");
|
||||
emit_operand_helper(raw_encode(reg), raw_encode(base), raw_encode(index),
|
||||
scale, disp, rspec, rip_relative_correction);
|
||||
|
||||
}
|
||||
void Assembler::emit_operand(XMMRegister xmmreg, Register base, Register index,
|
||||
Address::ScaleFactor scale, int disp,
|
||||
RelocationHolder const& rspec) {
|
||||
if (UseAVX > 2) {
|
||||
int xreg_enc = reg->encoding();
|
||||
if (xreg_enc > 15) {
|
||||
XMMRegister new_reg = as_XMMRegister(xreg_enc & 0xf);
|
||||
emit_operand((Register)new_reg, base, index, scale, disp, rspec);
|
||||
return;
|
||||
}
|
||||
}
|
||||
emit_operand((Register)reg, base, index, scale, disp, rspec);
|
||||
assert(!index->is_valid() || index != rsp, "illegal addressing mode");
|
||||
assert(xmmreg->encoding() < 16 || UseAVX > 2, "not supported");
|
||||
emit_operand_helper(raw_encode(xmmreg), raw_encode(base), raw_encode(index),
|
||||
scale, disp, rspec);
|
||||
}
|
||||
|
||||
void Assembler::emit_operand(XMMRegister reg, Register base, XMMRegister index,
|
||||
void Assembler::emit_operand(XMMRegister xmmreg, Register base, XMMRegister xmmindex,
|
||||
Address::ScaleFactor scale, int disp,
|
||||
RelocationHolder const& rspec) {
|
||||
if (UseAVX > 2) {
|
||||
int xreg_enc = reg->encoding();
|
||||
int xmmindex_enc = index->encoding();
|
||||
XMMRegister new_reg = as_XMMRegister(xreg_enc & 0xf);
|
||||
XMMRegister new_index = as_XMMRegister(xmmindex_enc & 0xf);
|
||||
emit_operand((Register)new_reg, base, (Register)new_index, scale, disp, rspec);
|
||||
} else {
|
||||
emit_operand((Register)reg, base, (Register)index, scale, disp, rspec);
|
||||
}
|
||||
assert(xmmreg->encoding() < 16 || UseAVX > 2, "not supported");
|
||||
assert(xmmindex->encoding() < 16 || UseAVX > 2, "not supported");
|
||||
emit_operand_helper(raw_encode(xmmreg), raw_encode(base), raw_encode(xmmindex),
|
||||
scale, disp, rspec, /* rip_relative_correction */ 0);
|
||||
}
|
||||
|
||||
|
||||
// Secret local extension to Assembler::WhichOperand:
|
||||
#define end_pc_operand (_WhichOperand_limit)
|
||||
|
||||
@ -1102,13 +1147,6 @@ void Assembler::check_relocation(RelocationHolder const& rspec, int format) {
|
||||
}
|
||||
#endif // ASSERT
|
||||
|
||||
void Assembler::emit_operand32(Register reg, Address adr) {
|
||||
assert(reg->encoding() < 8, "no extended registers");
|
||||
assert(!adr.base_needs_rex() && !adr.index_needs_rex(), "no extended registers");
|
||||
emit_operand(reg, adr._base, adr._index, adr._scale, adr._disp,
|
||||
adr._rspec);
|
||||
}
|
||||
|
||||
void Assembler::emit_operand(Register reg, Address adr,
|
||||
int rip_relative_correction) {
|
||||
emit_operand(reg, adr._base, adr._index, adr._scale, adr._disp,
|
||||
@ -1125,26 +1163,6 @@ void Assembler::emit_operand(XMMRegister reg, Address adr) {
|
||||
}
|
||||
}
|
||||
|
||||
// MMX operations
|
||||
void Assembler::emit_operand(MMXRegister reg, Address adr) {
|
||||
assert(!adr.base_needs_rex() && !adr.index_needs_rex(), "no extended registers");
|
||||
emit_operand((Register)reg, adr._base, adr._index, adr._scale, adr._disp, adr._rspec);
|
||||
}
|
||||
|
||||
// work around gcc (3.2.1-7a) bug
|
||||
void Assembler::emit_operand(Address adr, MMXRegister reg) {
|
||||
assert(!adr.base_needs_rex() && !adr.index_needs_rex(), "no extended registers");
|
||||
emit_operand((Register)reg, adr._base, adr._index, adr._scale, adr._disp, adr._rspec);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::emit_farith(int b1, int b2, int i) {
|
||||
assert(isByte(b1) && isByte(b2), "wrong opcode");
|
||||
assert(0 <= i && i < 8, "illegal stack offset");
|
||||
emit_int16(b1, b2 + i);
|
||||
}
|
||||
|
||||
|
||||
// Now the Assembler instructions (identical for 32/64 bits)
|
||||
|
||||
void Assembler::adcl(Address dst, int32_t imm32) {
|
||||
@ -1972,11 +1990,6 @@ void Assembler::divss(XMMRegister dst, XMMRegister src) {
|
||||
emit_int16(0x5E, (0xC0 | encode));
|
||||
}
|
||||
|
||||
void Assembler::emms() {
|
||||
NOT_LP64(assert(VM_Version::supports_mmx(), ""));
|
||||
emit_int16(0x0F, 0x77);
|
||||
}
|
||||
|
||||
void Assembler::hlt() {
|
||||
emit_int8((unsigned char)0xF4);
|
||||
}
|
||||
@ -2740,24 +2753,6 @@ void Assembler::movlpd(XMMRegister dst, Address src) {
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
void Assembler::movq( MMXRegister dst, Address src ) {
|
||||
assert( VM_Version::supports_mmx(), "" );
|
||||
emit_int16(0x0F, 0x6F);
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
void Assembler::movq( Address dst, MMXRegister src ) {
|
||||
assert( VM_Version::supports_mmx(), "" );
|
||||
emit_int16(0x0F, 0x7F);
|
||||
// workaround gcc (3.2.1-7a) bug
|
||||
// In that version of gcc with only an emit_operand(MMX, Address)
|
||||
// gcc will tail jump and try and reverse the parameters completely
|
||||
// obliterating dst in the process. By having a version available
|
||||
// that doesn't need to swap the args at the tail jump the bug is
|
||||
// avoided.
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
void Assembler::movq(XMMRegister dst, Address src) {
|
||||
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
|
||||
InstructionMark im(this);
|
||||
@ -6221,6 +6216,30 @@ void Assembler::evpxorq(XMMRegister dst, XMMRegister nds, Address src, int vecto
|
||||
emit_operand(dst, src);
|
||||
}
|
||||
|
||||
void Assembler::vpternlogd(XMMRegister dst, int imm8, XMMRegister src2, XMMRegister src3, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "requires EVEX support");
|
||||
assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support");
|
||||
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
int encode = vex_prefix_and_encode(dst->encoding(), src2->encoding(), src3->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
|
||||
emit_int8(0x25);
|
||||
emit_int8((unsigned char)(0xC0 | encode));
|
||||
emit_int8(imm8);
|
||||
}
|
||||
|
||||
void Assembler::vpternlogd(XMMRegister dst, int imm8, XMMRegister src2, Address src3, int vector_len) {
|
||||
assert(VM_Version::supports_evex(), "requires EVEX support");
|
||||
assert(vector_len == Assembler::AVX_512bit || VM_Version::supports_avx512vl(), "requires VL support");
|
||||
assert(dst != xnoreg, "sanity");
|
||||
InstructionMark im(this);
|
||||
InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true);
|
||||
attributes.set_is_evex_instruction();
|
||||
attributes.set_address_attributes(/* tuple_type */ EVEX_FV, /* input_size_in_bits */ EVEX_64bit);
|
||||
vex_prefix(src3, src2->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes);
|
||||
emit_int8(0x25);
|
||||
emit_operand(dst, src3);
|
||||
emit_int8(imm8);
|
||||
}
|
||||
|
||||
// vinserti forms
|
||||
|
||||
@ -6830,6 +6849,11 @@ void Assembler::vzeroupper_uncached() {
|
||||
#ifndef _LP64
|
||||
// 32bit only pieces of the assembler
|
||||
|
||||
void Assembler::emms() {
|
||||
NOT_LP64(assert(VM_Version::supports_mmx(), ""));
|
||||
emit_int16(0x0F, 0x77);
|
||||
}
|
||||
|
||||
void Assembler::vzeroupper() {
|
||||
vzeroupper_uncached();
|
||||
}
|
||||
@ -6865,6 +6889,19 @@ void Assembler::decl(Register dst) {
|
||||
|
||||
// 64bit doesn't use the x87
|
||||
|
||||
void Assembler::emit_operand32(Register reg, Address adr) {
|
||||
assert(reg->encoding() < 8, "no extended registers");
|
||||
assert(!adr.base_needs_rex() && !adr.index_needs_rex(), "no extended registers");
|
||||
emit_operand(reg, adr._base, adr._index, adr._scale, adr._disp,
|
||||
adr._rspec);
|
||||
}
|
||||
|
||||
void Assembler::emit_farith(int b1, int b2, int i) {
|
||||
assert(isByte(b1) && isByte(b2), "wrong opcode");
|
||||
assert(0 <= i && i < 8, "illegal stack offset");
|
||||
emit_int16(b1, b2 + i);
|
||||
}
|
||||
|
||||
void Assembler::fabs() {
|
||||
emit_int16((unsigned char)0xD9, (unsigned char)0xE1);
|
||||
}
|
||||
@ -7719,15 +7756,6 @@ bool Assembler::reachable(AddressLiteral adr) {
|
||||
return is_simm32(disp);
|
||||
}
|
||||
|
||||
// Check if the polling page is not reachable from the code cache using rip-relative
|
||||
// addressing.
|
||||
bool Assembler::is_polling_page_far() {
|
||||
intptr_t addr = (intptr_t)os::get_polling_page();
|
||||
return ForceUnreachable ||
|
||||
!is_simm32(addr - (intptr_t)CodeCache::low_bound()) ||
|
||||
!is_simm32(addr - (intptr_t)CodeCache::high_bound());
|
||||
}
|
||||
|
||||
void Assembler::emit_data64(jlong data,
|
||||
relocInfo::relocType rtype,
|
||||
int format) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user