This commit is contained in:
Prasanta Sadhukhan 2020-04-10 11:47:09 +05:30
commit 6b0b851a7c
1619 changed files with 782299 additions and 72297 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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("@.*", ""))

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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");
}

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View 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

View File

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

View File

@ -62,6 +62,4 @@ const bool HaveVFP = true;
#endif
#endif
#define THREAD_LOCAL_POLL
#endif // CPU_ARM_GLOBALDEFINITIONS_ARM_HPP

View File

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

View File

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

View File

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

View File

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

View File

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

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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