Merge branch 'master' into JDK-8344159

This commit is contained in:
Archie L. Cobbs 2026-07-17 16:31:35 -05:00
commit 044cfc097d
1010 changed files with 75013 additions and 9558 deletions

View File

@ -37,13 +37,13 @@ runs:
- name: 'Check cache for already built JTReg'
id: get-cached
uses: actions/cache@v5
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: jtreg/installed
key: jtreg-${{ steps.version.outputs.value }}
- name: 'Checkout the JTReg source'
uses: actions/checkout@v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: openjdk/jtreg
ref: jtreg-${{ steps.version.outputs.value }}
@ -61,7 +61,7 @@ runs:
if: (steps.get-cached.outputs.cache-hit != 'true')
- name: 'Upload JTReg artifact'
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: bundles-jtreg-${{ steps.version.outputs.value }}
path: jtreg/installed

View File

@ -66,7 +66,7 @@ runs:
shell: bash
- name: 'Upload build logs'
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: failure-logs-${{ inputs.platform }}${{ inputs.debug-suffix }}
path: failure-logs
@ -74,7 +74,7 @@ runs:
# This is the best way I found to abort the job with an error message
- name: 'Notify about build failures'
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: core.setFailed('Build failed. See summary for details.')
if: steps.check.outputs.failure == 'true'

View File

@ -65,7 +65,7 @@ runs:
- name: 'Check cache for BootJDK'
id: get-cached-bootjdk
uses: actions/cache@v5
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: bootjdk/jdk
key: boot-jdk-${{ inputs.platform }}-${{ steps.sha256.outputs.value }}

View File

@ -54,14 +54,14 @@ runs:
steps:
- name: 'Download bundles artifact'
id: download-bundles
uses: actions/download-artifact@v8
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}
path: bundles
continue-on-error: true
- name: 'Download bundles artifact (retry)'
uses: actions/download-artifact@v8
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}
path: bundles
@ -69,7 +69,7 @@ runs:
- name: 'Download static bundles artifact'
id: download-static-bundles
uses: actions/download-artifact@v8
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}${{ inputs.static-suffix }}
path: bundles

View File

@ -40,7 +40,7 @@ runs:
var: GTEST_VERSION
- name: 'Checkout GTest source'
uses: actions/checkout@v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: google/googletest
ref: 'v${{ steps.version.outputs.value }}'

View File

@ -41,7 +41,7 @@ runs:
- name: 'Download JTReg artifact'
id: download-jtreg
uses: actions/download-artifact@v8
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: bundles-jtreg-${{ steps.version.outputs.value }}
path: jtreg/installed

View File

@ -35,7 +35,7 @@ runs:
steps:
- name: 'Install MSYS2 on x86.x64'
id: msys2-x64
uses: msys2/setup-msys2@v2.31.0
uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.32.0
with:
install: 'autoconf tar unzip zip make'
path-type: minimal
@ -44,7 +44,7 @@ runs:
- name: 'Install MSYS2 on ARM64'
id: msys2-arm64
uses: msys2/setup-msys2@v2.31.0
uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.32.0
with:
install: 'autoconf tar unzip zip make'
path-type: minimal

View File

@ -87,7 +87,7 @@ runs:
shell: bash
- name: 'Upload bundles artifact'
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: bundles-${{ inputs.platform }}${{ inputs.debug-suffix }}${{ inputs.static-suffix }}${{ inputs.bundle-suffix }}
path: bundles

View File

@ -74,7 +74,7 @@ jobs:
steps:
- name: 'Checkout the JDK source'
uses: actions/checkout@v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: 'Install toolchain and dependencies'
run: |

View File

@ -87,7 +87,7 @@ jobs:
steps:
- name: 'Checkout the JDK source'
uses: actions/checkout@v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: 'Get the BootJDK'
id: bootjdk
@ -115,7 +115,7 @@ jobs:
- name: 'Check cache for sysroot'
id: get-cached-sysroot
uses: actions/cache@v5
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: sysroot
key: sysroot-${{ matrix.debian-arch }}-${{ hashFiles('./.github/workflows/build-cross-compile.yml') }}

View File

@ -92,7 +92,7 @@ jobs:
steps:
- name: 'Checkout the JDK source'
uses: actions/checkout@v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: 'Get the BootJDK'
id: bootjdk

View File

@ -75,7 +75,7 @@ jobs:
steps:
- name: 'Checkout the JDK source'
uses: actions/checkout@v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: 'Get the BootJDK'
id: bootjdk

View File

@ -86,7 +86,7 @@ jobs:
steps:
- name: 'Checkout the JDK source'
uses: actions/checkout@v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: 'Get MSYS2'
uses: ./.github/actions/get-msys2

View File

@ -76,7 +76,7 @@ jobs:
steps:
- name: 'Checkout the scripts'
uses: actions/checkout@v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
sparse-checkout: |
.github

View File

@ -131,7 +131,7 @@ jobs:
steps:
- name: 'Checkout the JDK source'
uses: actions/checkout@v6
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- name: 'Get MSYS2'
uses: ./.github/actions/get-msys2
@ -244,7 +244,7 @@ jobs:
if: always()
- name: 'Upload test results'
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
path: results
name: ${{ steps.package.outputs.artifact-name }}
@ -252,7 +252,7 @@ jobs:
# This is the best way I found to abort the job with an error message
- name: 'Notify about test failures'
uses: actions/github-script@v8
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: core.setFailed('${{ steps.run-tests.outputs.error-message }}')
if: steps.run-tests.outputs.failure == 'true'

View File

@ -142,8 +142,7 @@ define CreateCDSArchive
$1_$2_COOPS_OPTION := $(if $(findstring _nocoops, $2),-XX:-UseCompressedOops)
# enable and also explicitly disable coh as needed.
ifeq ($(call isTargetCpuBits, 64), true)
$1_$2_NOCOH_OPTION := -XX:+UnlockExperimentalVMOptions \
$(if $(findstring _nocoh, $2),-XX:-UseCompactObjectHeaders,-XX:+UseCompactObjectHeaders)
$1_$2_NOCOH_OPTION := $(if $(findstring _nocoh, $2),-XX:-UseCompactObjectHeaders,-XX:+UseCompactObjectHeaders)
endif
$1_$2_DUMP_EXTRA_ARG := $$($1_$2_COOPS_OPTION) $$($1_$2_NOCOH_OPTION)
$1_$2_DUMP_TYPE := $(if $(findstring _nocoops, $2),-NOCOOPS,)$(if $(findstring _nocoh, $2),-NOCOH,)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -327,14 +327,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_DEVKIT],
elif test -d "$DEVKIT_ROOT/$host/sys-root"; then
SYSROOT="$DEVKIT_ROOT/$host/sys-root"
fi
if test "x$DEVKIT_ROOT" != x; then
DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib"
if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
DEVKIT_LIB_DIR="$DEVKIT_ROOT/lib64"
fi
AC_SUBST(DEVKIT_LIB_DIR)
fi
fi
# You can force the sysroot if the sysroot encoded into the compiler tools

View File

@ -148,7 +148,7 @@ AC_DEFUN([BASIC_CHECK_MAKE_VERSION],
if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
MAKE_EXPECTED_ENV='cygwin'
elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys2"; then
MAKE_EXPECTED_ENV='msys'
MAKE_EXPECTED_ENV='cygwin|msys'
elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl1" || test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.wsl2"; then
if test "x$OPENJDK_BUILD_CPU" = "xaarch64"; then
MAKE_EXPECTED_ENV='aarch64-.*-linux-gnu'
@ -159,7 +159,7 @@ AC_DEFUN([BASIC_CHECK_MAKE_VERSION],
AC_MSG_ERROR([Unknown Windows environment])
fi
MAKE_BUILT_FOR=`$MAKE_CANDIDATE --version | $GREP -i 'built for'`
IS_MAKE_CORRECT_ENV=`$ECHO $MAKE_BUILT_FOR | $GREP $MAKE_EXPECTED_ENV`
IS_MAKE_CORRECT_ENV=`$ECHO $MAKE_BUILT_FOR | $GREP -E $MAKE_EXPECTED_ENV`
else
# Not relevant for non-Windows
IS_MAKE_CORRECT_ENV=true

View File

@ -81,6 +81,7 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER],
fi
if test "x$ENABLE_LINKTIME_GC" = xtrue; then
BASIC_LDFLAGS_JVM_ONLY="$BASIC_LDFLAGS_JVM_ONLY -Wl,--gc-sections -Wl,--undefined=_ZTV8Metadata"
BASIC_LDFLAGS_JDK_ONLY="$BASIC_LDFLAGS_JDK_ONLY -Wl,--gc-sections"
fi
fi
@ -93,7 +94,7 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER],
elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
BASIC_LDFLAGS="-opt:ref"
BASIC_LDFLAGS_JDK_ONLY="-incremental:no"
BASIC_LDFLAGS_JVM_ONLY="-opt:icf,8 -subsystem:windows"
BASIC_LDFLAGS_JVM_ONLY="-opt:noicf -subsystem:windows"
LDFLAGS_LTO="-LTCG:INCREMENTAL"
fi

View File

@ -28,7 +28,7 @@
################################################################################
# Minimum supported versions
JTREG_MINIMUM_VERSION=8.2.1
JTREG_MINIMUM_VERSION=8.3
GTEST_MINIMUM_VERSION=1.14.0
################################################################################

View File

@ -174,18 +174,6 @@ AC_DEFUN([PLATFORM_EXTRACT_VARS_FROM_CPU],
VAR_CPU_BITS=64
VAR_CPU_ENDIAN=big
;;
sparc)
VAR_CPU=sparc
VAR_CPU_ARCH=sparc
VAR_CPU_BITS=32
VAR_CPU_ENDIAN=big
;;
sparcv9|sparc64)
VAR_CPU=sparcv9
VAR_CPU_ARCH=sparc
VAR_CPU_BITS=64
VAR_CPU_ENDIAN=big
;;
*)
AC_MSG_ERROR([unsupported cpu $1])
;;

View File

@ -116,7 +116,7 @@ Conv_A = \
# Return integer type with same size as the type
Conv_memtype = \
$(if $(filter float, $1), int, $(if $(filter double, $1), long, $1))
$(if $(filter float, $1), int, $(if $(filter double, $1), long, $(if $(filter boolean, $1), byte, $1)))
# Return capitalized integer type with same size as the type
Conv_Memtype = \

View File

@ -26,7 +26,7 @@
# Versions and download locations for dependencies used by GitHub Actions (GHA)
GTEST_VERSION=1.14.0
JTREG_VERSION=8.2.1+1
JTREG_VERSION=8.3+1
LINUX_X64_BOOT_JDK_EXT=tar.gz
LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk26/c3cc523845074aa0af4f5e1e1ed4151d/35/GPL/openjdk-26_linux-x64_bin.tar.gz

View File

@ -644,7 +644,7 @@ var getJibProfilesProfiles = function (input, common, data) {
// Bootcycle profiles runs the build with itself as the boot jdk. This can
// be done in two ways. Either using the builtin bootcycle target in the
// build system. Or by supplying the main jdk build as bootjdk to configure.
[ "linux-x64", "macosx-x64", "windows-x64", "linux-aarch64" ]
[ "linux-x64", "macosx-aarch64", "macosx-x64", "windows-x64", "linux-aarch64" ]
.forEach(function (name) {
var bootcycleName = name + "-bootcycle";
var bootcyclePrebuiltName = name + "-bootcycle-prebuilt";
@ -1174,9 +1174,9 @@ var getJibProfilesDependencies = function (input, common) {
jtreg: {
server: "jpg",
product: "jtreg",
version: "8.2.1",
version: "8.3",
build_number: "1",
file: "bundles/jtreg-8.2.1+1.zip",
file: "bundles/jtreg-8.3+1.zip",
environment_name: "JT_HOME",
environment_path: input.get("jtreg", "home_path") + "/bin",
configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"),

View File

@ -28,7 +28,7 @@
# PLATFORM_MODULES are modules defined by the platform loader
#
# All other modules not declared below are defined by the application loader
# and are not included in JRE.
# and are not included in the JDK runtime image.
BOOT_MODULES= \
java.base \
@ -52,7 +52,6 @@ BOOT_MODULES= \
jdk.nio.mapmode \
jdk.sctp \
jdk.unsupported \
jdk.naming.rmi \
#
# Modules that directly or indirectly requiring upgradeable modules
@ -78,6 +77,7 @@ PLATFORM_MODULES= \
jdk.httpserver \
jdk.localedata \
jdk.naming.dns \
jdk.naming.rmi \
jdk.security.auth \
jdk.security.jgss \
jdk.xml.dom \

View File

@ -88,8 +88,7 @@ SRCDIR := $(OUTPUT_ROOT)/src
DOWNLOAD_RPMS_MARKER := $(BUILDDIR)/download-rpms.marker
RPMS_UNPACKED_MARKER := $(BUILDDIR)/rpms_unpacked.marker
UNPATCHED_SYSROOT_MARKER := $(BUILDDIR)/sysroot_unpatched.marker
PATCHED_SYSROOT_MARKER := $(BUILDDIR)/sysroot_patched.marker
SYSROOT_MARKER := $(BUILDDIR)/sysroot.marker
################################################################################
# Download RPMs
@ -101,10 +100,6 @@ else
endif
RPM_ARCHS := $(RPM_ARCH) noarch
ifeq ($(ARCH), x86_64)
# Enable mixed mode.
RPM_ARCHS += i386 i686
endif
EMPTY :=
SPACE := $(EMPTY) $(EMPTY)
@ -166,43 +161,12 @@ $(RPMS_UNPACKED_MARKER): $(DOWNLOAD_RPMS_MARKER)
################################################################################
$(UNPATCHED_SYSROOT_MARKER): $(RPMS_UNPACKED_MARKER)
$(SYSROOT_MARKER): $(RPMS_UNPACKED_MARKER)
touch $@
################################################################################
# Patch sysroot
# Note: MUST create a <sysroot>/usr/lib even if not really needed.
# gcc will use a path relative to it to resolve lib64. (x86_64).
# we're creating multi-lib compiler with 32bit libc as well, so we should
# have it anyway, but just to make sure...
# Patch GNU ld scripts to force linking against libraries in the sysroot
# and not the ones installed on the build machine.
LD_SCRIPT_PATCHES := \
-e 's|/usr/lib64/||g' \
-e 's|/usr/lib/||g' \
-e 's|/lib64/||g' \
-e 's|/lib/||g' \
#
$(PATCHED_SYSROOT_MARKER): $(UNPATCHED_SYSROOT_MARKER)
@echo Patching GNU ld scripts
@( \
for f in $$(find $(SYSROOT) -name "*.so" -type f 2>/dev/null); do \
if grep -Iq 'GNU ld script' "$$f"; then \
sed $(LD_SCRIPT_PATCHES) "$$f" > "$$f.tmp" && \
mv "$$f.tmp" "$$f"; \
fi; \
done \
)
@mkdir -p $(SYSROOT)/usr/lib
@touch $@
################################################################################
download-rpms: $(DOWNLOAD_RPMS_MARKER)
unpatched-sysroot: $(UNPATCHED_SYSROOT_MARKER)
sysroot: $(PATCHED_SYSROOT_MARKER)
sysroot: $(SYSROOT_MARKER)
.PHONY: download-rpms unpatched-sysroot sysroot
.PHONY: download-rpms sysroot

View File

@ -103,16 +103,6 @@ ifneq ($(REQUIRED_MIN_MAKE_MAJOR_VERSION),)
endif
################################################################################
# Define common directories and files
# Ensure we have 32-bit libs also for x64. We enable mixed-mode.
ifeq (x86_64,$(ARCH))
LIBDIRS := lib64 lib
CFLAGS_lib := -m32
else
LIBDIRS := lib
endif
# Define directories
DOWNLOAD := $(OUTPUT_ROOT)/download
SRCDIR := $(OUTPUT_ROOT)/src
@ -200,23 +190,19 @@ TOOLS ?= $(call declare_tools,_FOR_TARGET,$(TARGET)-)
################################################################################
# Create a TARGET bfd + libiberty only.
# Configure one or two times depending on mulitlib arch.
# If multilib, the second should be 32-bit, and we resolve
# CFLAG_<name> to most likely -m32.
define mk_bfd
$$(info Libs for $(1))
$$(BUILDDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1))/Makefile: \
CFLAGS += $$(CFLAGS_$(1))
$$(BUILDDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1))/Makefile: \
LIBDIRS = --libdir=$(TARGETDIR)/$(1)
ifeq (x86_64,$(ARCH))
LIBDIR := lib64
else
LIBDIR := lib
endif
BFDLIB += $$(TARGETDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1)).done
BFDMAKES += $$(BUILDDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1))/Makefile
endef
$(BUILDDIR)/$(BINUTILS_VER)-$(LIBDIR)/Makefile:
CFLAGS += CFLAGS_$(LIBDIR)
$(BUILDDIR)/$(BINUTILS_VER)-$(LIBDIR)/Makefile:
LIBDIR = --libdir=$(TARGETDIR)/$(LIBDIR)
# Create one set of bfds etc for each multilib arch
$(foreach l,$(LIBDIRS),$(eval $(call mk_bfd,$(l))))
BFDLIB += $(TARGETDIR)/$(BINUTILS_VER)-$(LIBDIR).done
BFDMAKES += $(BUILDDIR)/$(BINUTILS_VER)-$(LIBDIR)/Makefile
# Only build these two libs.
$(BFDLIB): MAKECMD = all-libiberty all-bfd
@ -228,7 +214,7 @@ $(BFDMAKES): CONFIG = --target=$(TARGET) \
--host=$(TARGET) --build=$(BUILD) \
--prefix=$(TARGETDIR) \
--with-sysroot=$(SYSROOT) \
$(LIBDIRS)
$(LIBDIR)
$(BFDMAKES): TOOLS = $(call declare_tools,_FOR_TARGET,$(TARGET)-) $(call declare_tools,,$(TARGET)-)
@ -243,11 +229,8 @@ $(GCC) \
$(CCACHE): ENVS += $(TOOLS)
# libdir to work around hateful bfd stuff installing into wrong dirs...
# ensure we have 64 bit bfd support in the HOST library. I.e our
# compiler on i686 will know 64 bit symbols, BUT later
# we build just the libs again for TARGET, then with whatever the arch
# wants.
$(BUILDDIR)/$(BINUTILS_VER)/Makefile: CONFIG += --enable-64-bit-bfd --libdir=$(PREFIX)/$(word 1,$(LIBDIRS))
# ensure we have 64 bit bfd support in the HOST library.
$(BUILDDIR)/$(BINUTILS_VER)/Makefile: CONFIG += --enable-64-bit-bfd --libdir=$(PREFIX)/$(LIBDIR)
ifeq ($(filter $(ARCH), s390x riscv64 ppc64le), )
# gold compiles but cannot link properly on s390x @ gcc 13.2 and Fedore 41
@ -256,10 +239,6 @@ ifeq ($(filter $(ARCH), s390x riscv64 ppc64le), )
LINKER_CONFIG_ENABLE_GOLD := --enable-gold=default
endif
ifeq ($(filter riscv64 ppc64le s390x armhfp, $(ARCH)), )
ENABLE_MULTILIB := --enable-multilib
endif
# Makefile creation. Simply run configure in build dir.
# Setting CFLAGS to -O2 generates a much faster ld.
$(BFDMAKES) \
@ -274,8 +253,8 @@ $(BUILDDIR)/$(BINUTILS_VER)/Makefile: $(BINUTILS_CFG)
$(LINKER_CONFIG_ENABLE_GOLD) \
--with-sysroot=$(SYSROOT) \
--disable-nls \
--disable-gprofng \
--program-prefix=$(TARGET)- \
$(ENABLE_MULTILIB) \
--enable-threads \
--enable-plugins \
) > $(@D)/log.config 2>&1
@ -340,15 +319,12 @@ ifeq ($(ARCH), riscv64)
$(BUILDDIR)/$(GCC_VER)/Makefile: CONFIG += --disable-libsanitizer
endif
ifneq ($(filter riscv64 ppc64le s390x armhfp, $(ARCH)), )
# We only support 64-bit on these platforms anyway
CONFIG += --disable-multilib
endif
# We don't need to support multilib
CONFIG += --disable-multilib
# Want:
# c,c++
# shared libs
# multilib (-m32/-m64 on x64)
# skip native language.
# and link and assemble with the binutils we created
# earlier, so --with-gnu*
@ -438,14 +414,12 @@ ifeq ($(HOST),$(TARGET))
# "Solve" this by create links from the target libdirs to where they are.
$(LINK_LIBS_MARKER): $(GCC)
@echo -n 'Creating library symlinks...'
@for l in $(LIBDIRS); do \
for f in `cd $(PREFIX)/$$l && ls`; do \
if [ ! -e $(TARGETDIR)/$$l/$$f ]; then \
mkdir -p $(TARGETDIR)/$$l && \
cd $(TARGETDIR)/$$l/ && \
ln -fs ../../$$l/$$f $$f; \
fi \
done \
@for f in `cd $(PREFIX)/$(LIBDIR) && ls`; do \
if [ ! -e $(TARGETDIR)/$(LIBDIR)/$$f ]; then \
mkdir -p $(TARGETDIR)/$(LIBDIR) && \
cd $(TARGETDIR)/$(LIBDIR)/ && \
ln -fs ../../$(LIBDIR)/$$f $$f; \
fi \
done
@touch $@
@echo 'done'

View File

@ -173,6 +173,10 @@ ifeq ($(call check-jvm-feature, link-time-opt), true)
ifneq ($(call isCompiler, microsoft), true)
JVM_LDFLAGS_FEATURES += $(CXX_O_FLAG_HIGHEST_JVM)
endif
# avoid elimination of Metadata vtable when using LTO (important for serviceability agent)
ifeq ($(call isCompiler, gcc), true)
JVM_LDFLAGS_FEATURES += -Wl,--undefined=_ZTV8Metadata
endif
else
JVM_LTO := false
ifeq ($(call isCompiler, gcc), true)

View File

@ -33,10 +33,6 @@ ifeq ($(INCLUDE), true)
ifeq ($(TOOLCHAIN_TYPE), gcc)
BUILD_LIBJVM_vmStructs.cpp_CXXFLAGS := -fno-var-tracking-assignments
ifeq ($(DEBUG_LEVEL), release)
# Need extra inlining to collapse shared marking code into the hot marking loop
BUILD_LIBJVM_shenandoahMark.cpp_CXXFLAGS := --param inline-unit-growth=1000
endif
# disable lto in g1ParScanThreadState because of special inlining/flattening used there
ifeq ($(call check-jvm-feature, link-time-opt), true)
BUILD_LIBJVM_g1ParScanThreadState.cpp_CXXFLAGS := -fno-lto

View File

@ -29,6 +29,7 @@ import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Formatter;
import java.util.HashSet;
import java.util.HashMap;
@ -39,6 +40,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.SortedSet;
import java.util.stream.Collectors;
import static java.util.ResourceBundle.Control;
class ResourceBundleGenerator implements BundleGenerator {
// preferred timezones - keeping compatibility with JDK1.1 3 letter abbreviations
@ -69,6 +71,9 @@ class ResourceBundleGenerator implements BundleGenerator {
// For duplicated values
private static final String META_VALUE_PREFIX = "metaValue_";
// locales in the base module
private final Set<Locale> baseModuleLocales = new HashSet<>();
@Override
public void generateBundle(String packageName, String baseName, String localeID,
Map<String, ?> map, BundleType type) throws IOException {
@ -80,8 +85,15 @@ class ResourceBundleGenerator implements BundleGenerator {
return;
}
// Assume that non-base resources go into jdk.localedata
if (!CLDRConverter.isBaseModule) {
if (CLDRConverter.isBaseModule) {
if (!localeID.equals("root")) {
baseModuleLocales.addAll(
Control.getControl(Control.FORMAT_DEFAULT)
.getCandidateLocales("",
Locale.forLanguageTag(CLDRConverter.toLanguageTag(localeID))));
}
} else {
// Assume that non-base resources go into jdk.localedata
dirName = dirName + File.separator + "ext";
packageName = packageName + ".ext";
}
@ -284,6 +296,7 @@ class ResourceBundleGenerator implements BundleGenerator {
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import sun.util.locale.provider.LocaleDataMetaInfo;
import sun.util.locale.provider.LocaleProviderAdapter;
@ -296,6 +309,7 @@ class ResourceBundleGenerator implements BundleGenerator {
out.printf("""
private static final Map<Locale, String[]> parentLocalesMap = HashMap.newHashMap(%d);
private static final Map<String, String> languageAliasMap = HashMap.newHashMap(%d);
private static final Set<Locale> baseModuleLocales;
static final boolean nonlikelyScript = %s; // package access from CLDRLocaleProviderAdapter
static {
@ -322,7 +336,23 @@ class ResourceBundleGenerator implements BundleGenerator {
CLDRConverter.handlerSupplMeta.getLanguageAliasData().forEach((key, value) -> {
out.printf(" languageAliasMap.put(\"%s\", \"%s\");\n", CLDRConverter.escape(key), CLDRConverter.escape(value));
});
out.printf(" }\n\n");
out.println();
// for baseModuleLocales
out.printf(" baseModuleLocales = Set.of(\n");
out.printf(" %s",
baseModuleLocales.stream()
.map(Locale::toLanguageTag)
.sorted(Comparator.comparing(l -> l.equals("und") ? "" : l))
.map(l -> switch(l) {
case "und" -> "Locale.ROOT";
case "en" -> "Locale.ENGLISH";
case "en-US" -> "Locale.US";
default -> "Locale.forLanguageTag(\"" + l + "\")";
})
.collect(Collectors.joining(",\n ")));
out.printf("\n );");
out.println("\n }\n");
// end of static initializer block.
@ -391,6 +421,10 @@ class ResourceBundleGenerator implements BundleGenerator {
return parentLocalesMap;
}
public Set<Locale> baseModuleLocales() {
return baseModuleLocales;
}
// package access from CLDRLocaleProviderAdapter
Map<String, String> likelyScriptMap() {
return CLDRMapHolder.likelyScriptMap;

View File

@ -111,7 +111,7 @@ define GenerateVarHandleMemorySegment
$1_KEYS += CAS
endif
ifneq ($$(filter boolean byte, $1),)
$1_KEYS += byte
$1_KEYS += ByteOrBoolean
endif
ifneq ($$(filter float double, $1),)
$1_KEYS += floatingPoint

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -35,8 +35,6 @@ ifeq ($(INCLUDE), true)
$(eval $(call SetupJdkLibrary, BUILD_LIBVERIFY, \
NAME := verify, \
OPTIMIZATION := HIGH, \
DISABLED_WARNINGS_gcc_check_code.c := unused-variable, \
DISABLED_WARNINGS_clang_check_code.c := unused-variable, \
EXTRA_HEADER_DIRS := libjava, \
JDK_LIBS := libjvm, \
))
@ -59,8 +57,6 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJAVA, \
ProcessImpl_md.c_CFLAGS := $(VERSION_CFLAGS), \
java_props_md.c_CFLAGS := \
-DARCHPROPNAME='"$(OPENJDK_TARGET_CPU_OSARCH)"', \
DISABLED_WARNINGS_gcc_ProcessImpl_md.c := unused-result, \
DISABLED_WARNINGS_clang_TimeZone_md.c := unused-variable, \
JDK_LIBS := libjvm, \
LIBS_linux := $(LIBDL), \
LIBS_aix := $(LIBDL) $(LIBM), \
@ -77,7 +73,7 @@ TARGETS += $(BUILD_LIBJAVA)
## Build libzip
################################################################################
BUILD_LIBZIP_EXCLUDES :=
LIBZIP_EXCLUDES :=
ifeq ($(USE_EXTERNAL_LIBZ), true)
LIBZIP_EXCLUDES += zlib
endif

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2026, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -30,15 +30,15 @@ include LauncherCommon.gmk
################################################################################
## Build jconsole
################################################################################
$(eval $(call SetupBuildLauncher, jconsole, \
MAIN_CLASS := sun.tools.jconsole.JConsole, \
JAVA_ARGS := \
--add-opens java.base/java.io=jdk.jconsole \
--add-modules ALL-DEFAULT \
-Djconsole.showOutputViewer \
-Djdk.attach.allowAttachSelf=true, \
WINDOWS_JAVAW := true, \
))
ifneq ($(ENABLE_HEADLESS_ONLY), true)
$(eval $(call SetupBuildLauncher, jconsole, \
MAIN_CLASS := sun.tools.jconsole.JConsole, \
JAVA_ARGS := \
--add-opens java.base/java.io=jdk.jconsole \
--add-modules ALL-DEFAULT \
-Djconsole.showOutputViewer \
-Djdk.attach.allowAttachSelf=true, \
WINDOWS_JAVAW := true, \
))
endif
################################################################################

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -41,8 +41,6 @@ endif
$(eval $(call SetupJdkLibrary, BUILD_LIBMANAGEMENT_EXT, \
NAME := management_ext, \
OPTIMIZATION := HIGH, \
DISABLED_WARNINGS_gcc_DiagnosticCommandImpl.c := unused-variable, \
DISABLED_WARNINGS_clang_DiagnosticCommandImpl.c := unused-variable, \
DISABLED_WARNINGS_clang_UnixOperatingSystem.c := format-nonliteral, \
CFLAGS := $(LIBMANAGEMENT_EXT_CFLAGS), \
JDK_LIBS := java.base:libjava java.base:libjvm, \

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2015, 2026, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -69,6 +69,9 @@ ifeq ($(call isTargetOs, linux), true)
HOTSPOT_JTREG_LIBRARIES_LIBS_libatExit += -ldl
HOTSPOT_JTREG_LIBRARIES_LIBS_libAsyncGetCallTraceTest := -ldl
HOTSPOT_JTREG_LIBRARIES_LDFLAGS_libfast-math := -ffast-math
ifeq ($(call isTargetCpuBits, 32), true)
HOTSPOT_JTREG_LIBRARIES_LIBS_libSuspendInCritical += -latomic
endif
else
HOTSPOT_JTREG_EXCLUDE += libtest-rw.c libtest-rwx.c \
exeinvoke.c exestack-gap.c exestack-tls.c libAsyncGetCallTraceTest.cpp

View File

@ -1198,8 +1198,12 @@ class HandlerImpl {
static int emit_deopt_handler(C2_MacroAssembler* masm);
static uint size_deopt_handler() {
// count one branch instruction and one far call instruction sequence
return NativeInstruction::instruction_size + MacroAssembler::far_codestub_branch_size();
bool use_far_branch = MacroAssembler::target_needs_far_branch(SharedRuntime::deopt_blob()->unpack());
// far: adrp, add, blr; near: bl
uint target_branch_instructions = use_far_branch ? 3 : 1;
// target branch + one branch instruction
uint deopt_handler_instructions = target_branch_instructions + 1;
return deopt_handler_instructions * NativeInstruction::instruction_size;
}
};
@ -2512,25 +2516,25 @@ uint Matcher::float_pressure_limit()
return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.size() : FLOATPRESSURE;
}
const RegMask& Matcher::divI_proj_mask() {
const RegMask& Matcher::firstI_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}
// Register for MODI projection of divmodI.
const RegMask& Matcher::modI_proj_mask() {
// Register for the second projection of an int pair
const RegMask& Matcher::secondI_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}
// Register for DIVL projection of divmodL.
const RegMask& Matcher::divL_proj_mask() {
// Register for the first projection of a long pair
const RegMask& Matcher::firstL_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}
// Register for MODL projection of divmodL.
const RegMask& Matcher::modL_proj_mask() {
// Register for the second projection of a long pair
const RegMask& Matcher::secondL_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}
@ -8224,7 +8228,7 @@ instruct encodeKlass_not_null(iRegNNoSp dst, iRegP src) %{
ins_encode %{
Register src_reg = as_Register($src$$reg);
Register dst_reg = as_Register($dst$$reg);
__ encode_klass_not_null(dst_reg, src_reg);
__ encode_klass_not_null(dst_reg, src_reg, rscratch1);
%}
ins_pipe(ialu_reg);
@ -8239,11 +8243,7 @@ instruct decodeKlass_not_null(iRegPNoSp dst, iRegN src) %{
ins_encode %{
Register src_reg = as_Register($src$$reg);
Register dst_reg = as_Register($dst$$reg);
if (dst_reg != src_reg) {
__ decode_klass_not_null(dst_reg, src_reg);
} else {
__ decode_klass_not_null(dst_reg);
}
__ decode_klass_not_null(dst_reg, src_reg, rscratch1);
%}
ins_pipe(ialu_reg);
@ -8294,6 +8294,34 @@ instruct castII_checked(iRegI dst, rFlagsReg cr)
ins_pipe(pipe_slow);
%}
// The unchecked and checked variants for CastII below both use iRegINoSp for src and dst
// as some consumers of CastII node like ConvHF2F forbid the stack pointer as an input
// (please see convHF2F_reg_reg rule which requires input to be in an iRegINoSp register).
instruct castII_nosp(iRegINoSp dst)
%{
predicate(VerifyConstraintCasts == 0);
match(Set dst (CastII dst));
size(0);
format %{ "# castII of $dst" %}
ins_encode(/* empty encoding */);
ins_cost(0);
ins_pipe(pipe_class_empty);
%}
instruct castII_checked_nosp(iRegINoSp dst, rFlagsReg cr)
%{
predicate(VerifyConstraintCasts > 0);
match(Set dst (CastII dst));
effect(KILL cr);
format %{ "# castII_checked of $dst" %}
ins_encode %{
__ verify_int_in_range(_idx, bottom_type()->is_int(), $dst$$Register, rscratch1);
%}
ins_pipe(pipe_slow);
%}
instruct castLL(iRegL dst)
%{
predicate(VerifyConstraintCasts == 0);

View File

@ -43,8 +43,7 @@ instruct compareAndExchangeB(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::byte, /*acquire*/ false, /*release*/ true,
/*weak*/ false, $res$$Register);
Assembler::byte, memory_order_release, $res$$Register);
__ sxtbw($res$$Register, $res$$Register);
%}
ins_pipe(pipe_slow);
@ -59,8 +58,7 @@ instruct compareAndExchangeS(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::halfword, /*acquire*/ false, /*release*/ true,
/*weak*/ false, $res$$Register);
Assembler::halfword, memory_order_release, $res$$Register);
__ sxthw($res$$Register, $res$$Register);
%}
ins_pipe(pipe_slow);
@ -75,8 +73,7 @@ instruct compareAndExchangeI(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ false, /*release*/ true,
/*weak*/ false, $res$$Register);
Assembler::word, memory_order_release, $res$$Register);
%}
ins_pipe(pipe_slow);
%}
@ -90,8 +87,7 @@ instruct compareAndExchangeL(iRegLNoSp res, indirect mem, iRegL oldval, iRegL ne
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ false, /*release*/ true,
/*weak*/ false, $res$$Register);
Assembler::xword, memory_order_release, $res$$Register);
%}
ins_pipe(pipe_slow);
%}
@ -106,8 +102,7 @@ instruct compareAndExchangeN(iRegNNoSp res, indirect mem, iRegN oldval, iRegN ne
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ false, /*release*/ true,
/*weak*/ false, $res$$Register);
Assembler::word, memory_order_release, $res$$Register);
%}
ins_pipe(pipe_slow);
%}
@ -122,8 +117,7 @@ instruct compareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP ne
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ false, /*release*/ true,
/*weak*/ false, $res$$Register);
Assembler::xword, memory_order_release, $res$$Register);
%}
ins_pipe(pipe_slow);
%}
@ -138,8 +132,7 @@ instruct compareAndExchangeBAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::byte, /*acquire*/ true, /*release*/ true,
/*weak*/ false, $res$$Register);
Assembler::byte, memory_order_seq_cst, $res$$Register);
__ sxtbw($res$$Register, $res$$Register);
%}
ins_pipe(pipe_slow);
@ -155,8 +148,7 @@ instruct compareAndExchangeSAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::halfword, /*acquire*/ true, /*release*/ true,
/*weak*/ false, $res$$Register);
Assembler::halfword, memory_order_seq_cst, $res$$Register);
__ sxthw($res$$Register, $res$$Register);
%}
ins_pipe(pipe_slow);
@ -172,8 +164,7 @@ instruct compareAndExchangeIAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ true, /*release*/ true,
/*weak*/ false, $res$$Register);
Assembler::word, memory_order_seq_cst, $res$$Register);
%}
ins_pipe(pipe_slow);
%}
@ -188,8 +179,7 @@ instruct compareAndExchangeLAcq(iRegLNoSp res, indirect mem, iRegL oldval, iRegL
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ true, /*release*/ true,
/*weak*/ false, $res$$Register);
Assembler::xword, memory_order_seq_cst, $res$$Register);
%}
ins_pipe(pipe_slow);
%}
@ -204,8 +194,7 @@ instruct compareAndExchangeNAcq(iRegNNoSp res, indirect mem, iRegN oldval, iRegN
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ true, /*release*/ true,
/*weak*/ false, $res$$Register);
Assembler::word, memory_order_seq_cst, $res$$Register);
%}
ins_pipe(pipe_slow);
%}
@ -220,8 +209,7 @@ instruct compareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRegP
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ true, /*release*/ true,
/*weak*/ false, $res$$Register);
Assembler::xword, memory_order_seq_cst, $res$$Register);
%}
ins_pipe(pipe_slow);
%}
@ -235,9 +223,7 @@ instruct compareAndSwapB(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::byte, /*acquire*/ false, /*release*/ true,
/*weak*/ false, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::byte, memory_order_release);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -252,9 +238,7 @@ instruct compareAndSwapS(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::halfword, /*acquire*/ false, /*release*/ true,
/*weak*/ false, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::halfword, memory_order_release);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -269,9 +253,7 @@ instruct compareAndSwapI(iRegINoSp res, indirect mem, iRegI oldval, iRegI newval
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ false, /*release*/ true,
/*weak*/ false, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_release);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -286,9 +268,7 @@ instruct compareAndSwapL(iRegINoSp res, indirect mem, iRegL oldval, iRegL newval
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ false, /*release*/ true,
/*weak*/ false, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_release);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -304,9 +284,7 @@ instruct compareAndSwapN(iRegINoSp res, indirect mem, iRegN oldval, iRegN newval
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ false, /*release*/ true,
/*weak*/ false, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_release);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -322,9 +300,7 @@ instruct compareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newval
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ false, /*release*/ true,
/*weak*/ false, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_release);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -340,9 +316,7 @@ instruct compareAndSwapBAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI new
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::byte, /*acquire*/ true, /*release*/ true,
/*weak*/ false, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::byte, memory_order_seq_cst);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -358,9 +332,7 @@ instruct compareAndSwapSAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI new
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::halfword, /*acquire*/ true, /*release*/ true,
/*weak*/ false, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::halfword, memory_order_seq_cst);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -376,9 +348,7 @@ instruct compareAndSwapIAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI new
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ true, /*release*/ true,
/*weak*/ false, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_seq_cst);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -394,9 +364,7 @@ instruct compareAndSwapLAcq(iRegINoSp res, indirect mem, iRegL oldval, iRegL new
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ true, /*release*/ true,
/*weak*/ false, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_seq_cst);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -412,9 +380,7 @@ instruct compareAndSwapNAcq(iRegINoSp res, indirect mem, iRegN oldval, iRegN new
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ true, /*release*/ true,
/*weak*/ false, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_seq_cst);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -430,9 +396,7 @@ instruct compareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP new
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ true, /*release*/ true,
/*weak*/ false, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_seq_cst);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -447,9 +411,7 @@ instruct weakCompareAndSwapB(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::byte, /*acquire*/ false, /*release*/ true,
/*weak*/ true, noreg);
__ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::byte, memory_order_release);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -464,9 +426,7 @@ instruct weakCompareAndSwapS(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::halfword, /*acquire*/ false, /*release*/ true,
/*weak*/ true, noreg);
__ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::halfword, memory_order_release);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -481,9 +441,7 @@ instruct weakCompareAndSwapI(iRegINoSp res, indirect mem, iRegI oldval, iRegI ne
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ false, /*release*/ true,
/*weak*/ true, noreg);
__ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_release);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -498,9 +456,7 @@ instruct weakCompareAndSwapL(iRegINoSp res, indirect mem, iRegL oldval, iRegL ne
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ false, /*release*/ true,
/*weak*/ true, noreg);
__ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_release);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -516,9 +472,7 @@ instruct weakCompareAndSwapN(iRegINoSp res, indirect mem, iRegN oldval, iRegN ne
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ false, /*release*/ true,
/*weak*/ true, noreg);
__ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_release);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -534,9 +488,7 @@ instruct weakCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP ne
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ false, /*release*/ true,
/*weak*/ true, noreg);
__ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_release);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -552,9 +504,7 @@ instruct weakCompareAndSwapBAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::byte, /*acquire*/ true, /*release*/ true,
/*weak*/ true, noreg);
__ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::byte, memory_order_seq_cst);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -570,9 +520,7 @@ instruct weakCompareAndSwapSAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::halfword, /*acquire*/ true, /*release*/ true,
/*weak*/ true, noreg);
__ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::halfword, memory_order_seq_cst);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -588,9 +536,7 @@ instruct weakCompareAndSwapIAcq(iRegINoSp res, indirect mem, iRegI oldval, iRegI
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ true, /*release*/ true,
/*weak*/ true, noreg);
__ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_seq_cst);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -606,9 +552,7 @@ instruct weakCompareAndSwapLAcq(iRegINoSp res, indirect mem, iRegL oldval, iRegL
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ true, /*release*/ true,
/*weak*/ true, noreg);
__ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_seq_cst);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -624,9 +568,7 @@ instruct weakCompareAndSwapNAcq(iRegINoSp res, indirect mem, iRegN oldval, iRegN
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::word, /*acquire*/ true, /*release*/ true,
/*weak*/ true, noreg);
__ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_seq_cst);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -642,9 +584,7 @@ instruct weakCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::xword, /*acquire*/ true, /*release*/ true,
/*weak*/ true, noreg);
__ cmpxchg_weak($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_seq_cst);
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);

View File

@ -53,8 +53,7 @@ ifelse($7,Acq,INDENT(predicate(needs_acquiring_load_exclusive(n));),`dnl')
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::$4, /*acquire*/ ifelse($7,Acq,true,false), /*release*/ true,
/*weak*/ false, $res$$Register);
Assembler::$4, ifelse($7,Acq,memory_order_seq_cst,memory_order_release), $res$$Register);
__ $6($res$$Register, $res$$Register);
%}
ins_pipe(pipe_slow);
@ -76,8 +75,7 @@ ifelse($1$6,PAcq,INDENT(predicate(needs_acquiring_load_exclusive(n) && (n->as_Lo
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::$4, /*acquire*/ ifelse($6,Acq,true,false), /*release*/ true,
/*weak*/ false, $res$$Register);
Assembler::$4, ifelse($6,Acq,memory_order_seq_cst,memory_order_release), $res$$Register);
%}
ins_pipe(pipe_slow);
%}')dnl
@ -112,9 +110,7 @@ ifelse($6,Acq,INDENT(predicate(needs_acquiring_load_exclusive(n));),`dnl')
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::$4, /*acquire*/ ifelse($6,Acq,true,false), /*release*/ true,
/*weak*/ ifelse($7,Weak,true,false), noreg);
__ ifelse($7,Weak,cmpxchg_weak,cmpxchg)($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::$4, ifelse($6,Acq,memory_order_seq_cst,memory_order_release));
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);
@ -137,9 +133,7 @@ ifelse($1$6,PAcq,INDENT(predicate(needs_acquiring_load_exclusive(n) && (n->as_Lo
"csetw $res, EQ\t# $res <-- (EQ ? 1 : 0)"
%}
ins_encode %{
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register,
Assembler::$4, /*acquire*/ ifelse($6,Acq,true,false), /*release*/ true,
/*weak*/ ifelse($7,Weak,true,false), noreg);
__ ifelse($7,Weak,cmpxchg_weak,cmpxchg)($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::$4, ifelse($6,Acq,memory_order_seq_cst,memory_order_release));
__ csetw($res$$Register, Assembler::EQ);
%}
ins_pipe(pipe_slow);

View File

@ -251,9 +251,9 @@ source %{
return false;
}
break;
// At the time of writing this, the Vector API has no half-float (FP16) species.
// Consequently, AddReductionVHF and MulReductionVHF are only produced by the
// auto-vectorizer, which requires strictly ordered semantics for FP reductions.
// AddReductionVHF and MulReductionVHF are currently only produced by the
// auto-vectorizer (the Vector API does not yet intrinsify Float16 reductions),
// which requires strictly ordered semantics for FP reductions.
//
// There is no direct Neon instruction that performs strictly ordered floating
// point add reduction. Hence, on Neon only machines, the add reduction operation
@ -317,6 +317,13 @@ source %{
return false; // NEON only, since SLI/USHR are not available in SVE
}
break;
case Op_VectorBitwiseBlend:
// Use NEON BSL when UseSVE < 2; SVE1 has no BSL so larger vectors are
// not supported on UseSVE == 1 machines.
if (UseSVE < 2 && length_in_bytes > 16) {
return false;
}
break;
default:
break;
}
@ -340,6 +347,7 @@ source %{
case Op_MulReductionVL:
case Op_CompressBitsV:
case Op_ExpandBitsV:
case Op_VectorBitwiseBlend:
return false;
case Op_SaturatingAddV:
case Op_SaturatingSubV:
@ -364,9 +372,9 @@ source %{
opcode = Op_StoreVectorScatterMasked;
break;
// Currently, the masked versions of the following 8 Float16 operations are disabled.
// When the support for Float16 vector classes is added in VectorAPI and the masked
// Float16 IR can be generated, these masked operations will be enabled and relevant
// backend support added.
// The Vector API does not yet emit predicated Float16 IR. When such masked IR can be
// generated, these masked operations will be enabled and the relevant backend support
// added.
case Op_AddVHF:
case Op_SubVHF:
case Op_MulVHF:
@ -1149,7 +1157,8 @@ instruct vmulI_sve(vReg dst_src1, vReg src2) %{
// vector mul - LONG
instruct vmulL_neon(vReg dst, vReg src1, vReg src2) %{
predicate(UseSVE == 0);
predicate(UseSVE == 0 && !n->as_MulVL()->has_int_inputs() &&
!n->as_MulVL()->has_uint_inputs());
match(Set dst (MulVL src1 src2));
format %{ "vmulL_neon $dst, $src1, $src2\t# 2L" %}
ins_encode %{
@ -1167,8 +1176,75 @@ instruct vmulL_neon(vReg dst, vReg src1, vReg src2) %{
ins_pipe(pipe_slow);
%}
// Specialization of vmulL_int_neon when both inputs are the same IR node
// (e.g. v * v). Avoids one redundant xtn and saves one temporary register.
instruct vmulL_int_neon_same(vReg dst, vReg src, vReg tmp) %{
predicate(UseSVE == 0 && n->as_MulVL()->has_int_inputs() &&
n->in(1) == n->in(2));
match(Set dst (MulVL src src));
effect(TEMP tmp);
format %{ "vmulL_int_neon_same $dst, $src, $src\t# 2L. KILL $tmp" %}
ins_encode %{
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
assert(length_in_bytes == 16, "must be");
__ xtn($tmp$$FloatRegister, __ T2S, $src$$FloatRegister, __ T2D);
__ smullv($dst$$FloatRegister, __ T2S, $tmp$$FloatRegister, $tmp$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
instruct vmulL_int_neon(vReg dst, vReg src1, vReg src2, vReg tmp1, vReg tmp2) %{
predicate(UseSVE == 0 && n->as_MulVL()->has_int_inputs() &&
n->in(1) != n->in(2));
match(Set dst (MulVL src1 src2));
effect(TEMP tmp1, TEMP tmp2);
format %{ "vmulL_int_neon $dst, $src1, $src2\t# 2L. KILL $tmp1, $tmp2" %}
ins_encode %{
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
assert(length_in_bytes == 16, "must be");
__ xtn($tmp1$$FloatRegister, __ T2S, $src1$$FloatRegister, __ T2D);
__ xtn($tmp2$$FloatRegister, __ T2S, $src2$$FloatRegister, __ T2D);
__ smullv($dst$$FloatRegister, __ T2S, $tmp1$$FloatRegister, $tmp2$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
// Specialization of vmulL_uint_neon when both inputs are the same IR node
// (e.g. v * v). Avoids one redundant xtn and saves one temporary register.
instruct vmulL_uint_neon_same(vReg dst, vReg src, vReg tmp) %{
predicate(UseSVE == 0 && n->as_MulVL()->has_uint_inputs() &&
n->in(1) == n->in(2));
match(Set dst (MulVL src src));
effect(TEMP tmp);
format %{ "vmulL_uint_neon_same $dst, $src, $src\t# 2L. KILL $tmp" %}
ins_encode %{
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
assert(length_in_bytes == 16, "must be");
__ xtn($tmp$$FloatRegister, __ T2S, $src$$FloatRegister, __ T2D);
__ umullv($dst$$FloatRegister, __ T2S, $tmp$$FloatRegister, $tmp$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
instruct vmulL_uint_neon(vReg dst, vReg src1, vReg src2, vReg tmp1, vReg tmp2) %{
predicate(UseSVE == 0 && n->as_MulVL()->has_uint_inputs() &&
n->in(1) != n->in(2));
match(Set dst (MulVL src1 src2));
effect(TEMP tmp1, TEMP tmp2);
format %{ "vmulL_uint_neon $dst, $src1, $src2\t# 2L. KILL $tmp1, $tmp2" %}
ins_encode %{
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
assert(length_in_bytes == 16, "must be");
__ xtn($tmp1$$FloatRegister, __ T2S, $src1$$FloatRegister, __ T2D);
__ xtn($tmp2$$FloatRegister, __ T2S, $src2$$FloatRegister, __ T2D);
__ umullv($dst$$FloatRegister, __ T2S, $tmp1$$FloatRegister, $tmp2$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
instruct vmulL_sve(vReg dst_src1, vReg src2) %{
predicate(UseSVE > 0);
predicate(UseSVE == 1 || (UseSVE == 2 && !n->as_MulVL()->has_int_inputs() &&
!n->as_MulVL()->has_uint_inputs()));
match(Set dst_src1 (MulVL dst_src1 src2));
format %{ "vmulL_sve $dst_src1, $dst_src1, $src2" %}
ins_encode %{
@ -1177,6 +1253,26 @@ instruct vmulL_sve(vReg dst_src1, vReg src2) %{
ins_pipe(pipe_slow);
%}
instruct vmulL_int_sve2(vReg dst, vReg src1, vReg src2) %{
predicate(UseSVE == 2 && n->as_MulVL()->has_int_inputs());
match(Set dst (MulVL src1 src2));
format %{ "vmulL_int_sve2 $dst, $src1, $src2" %}
ins_encode %{
__ sve_smullb($dst$$FloatRegister, __ D, $src1$$FloatRegister, $src2$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
instruct vmulL_uint_sve2(vReg dst, vReg src1, vReg src2) %{
predicate(UseSVE == 2 && n->as_MulVL()->has_uint_inputs());
match(Set dst (MulVL src1 src2));
format %{ "vmulL_uint_sve2 $dst, $src1, $src2" %}
ins_encode %{
__ sve_umullb($dst$$FloatRegister, __ D, $src1$$FloatRegister, $src2$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
// vector mul - floating-point
instruct vmulHF(vReg dst, vReg src1, vReg src2) %{
@ -7051,6 +7147,31 @@ instruct vblend_sve(vReg dst, vReg src1, vReg src2, pReg pg) %{
ins_pipe(pipe_slow);
%}
// ------------------------------ Vector bitwise blend -------------------------
instruct vbitwise_blend_neon_sve1(vReg src1, vReg src2, vReg dst_src3) %{
predicate(UseSVE < 2 &&
VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n)));
match(Set dst_src3 (VectorBitwiseBlend (Binary src1 src2) dst_src3));
format %{ "vbitwise_blend_neon_sve1 $src1, $src2, $dst_src3" %}
ins_encode %{
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
Assembler::SIMD_Arrangement T = length_in_bytes == 16 ? __ T16B : __ T8B;
__ bsl($dst_src3$$FloatRegister, T, $src2$$FloatRegister, $src1$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
instruct vbitwise_blend_sve2(vReg src1, vReg dst_src2, vReg src3) %{
predicate(UseSVE == 2);
match(Set dst_src2 (VectorBitwiseBlend (Binary src1 dst_src2) src3));
format %{ "vbitwise_blend_sve2 $src1, $dst_src2, $src3" %}
ins_encode %{
__ sve_bsl($dst_src2$$FloatRegister, $src1$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
// ------------------------------ Vector round ---------------------------------
// vector Math.round

View File

@ -241,9 +241,9 @@ source %{
return false;
}
break;
// At the time of writing this, the Vector API has no half-float (FP16) species.
// Consequently, AddReductionVHF and MulReductionVHF are only produced by the
// auto-vectorizer, which requires strictly ordered semantics for FP reductions.
// AddReductionVHF and MulReductionVHF are currently only produced by the
// auto-vectorizer (the Vector API does not yet intrinsify Float16 reductions),
// which requires strictly ordered semantics for FP reductions.
//
// There is no direct Neon instruction that performs strictly ordered floating
// point add reduction. Hence, on Neon only machines, the add reduction operation
@ -307,6 +307,13 @@ source %{
return false; // NEON only, since SLI/USHR are not available in SVE
}
break;
case Op_VectorBitwiseBlend:
// Use NEON BSL when UseSVE < 2; SVE1 has no BSL so larger vectors are
// not supported on UseSVE == 1 machines.
if (UseSVE < 2 && length_in_bytes > 16) {
return false;
}
break;
default:
break;
}
@ -330,6 +337,7 @@ source %{
case Op_MulReductionVL:
case Op_CompressBitsV:
case Op_ExpandBitsV:
case Op_VectorBitwiseBlend:
return false;
case Op_SaturatingAddV:
case Op_SaturatingSubV:
@ -354,9 +362,9 @@ source %{
opcode = Op_StoreVectorScatterMasked;
break;
// Currently, the masked versions of the following 8 Float16 operations are disabled.
// When the support for Float16 vector classes is added in VectorAPI and the masked
// Float16 IR can be generated, these masked operations will be enabled and relevant
// backend support added.
// The Vector API does not yet emit predicated Float16 IR. When such masked IR can be
// generated, these masked operations will be enabled and the relevant backend support
// added.
case Op_AddVHF:
case Op_SubVHF:
case Op_MulVHF:
@ -728,7 +736,8 @@ BINARY_OP_NEON_SVE_PAIRWISE(vmulI, MulVI, mulv, sve_mul, S)
// vector mul - LONG
instruct vmulL_neon(vReg dst, vReg src1, vReg src2) %{
predicate(UseSVE == 0);
predicate(UseSVE == 0 && !n->as_MulVL()->has_int_inputs() &&
!n->as_MulVL()->has_uint_inputs());
match(Set dst (MulVL src1 src2));
format %{ "vmulL_neon $dst, $src1, $src2\t# 2L" %}
ins_encode %{
@ -746,8 +755,47 @@ instruct vmulL_neon(vReg dst, vReg src1, vReg src2) %{
ins_pipe(pipe_slow);
%}
dnl VMUL_L_NEON($1, $2 )
dnl VMUL_L_NEON(kind, insn )
define(`VMUL_L_NEON', `dnl
// Specialization of vmulL_$1_neon when both inputs are the same IR node
// (e.g. v * v). Avoids one redundant xtn and saves one temporary register.
instruct vmulL_$1_neon_same(vReg dst, vReg src, vReg tmp) %{
predicate(UseSVE == 0 && n->as_MulVL()->has_$1_inputs() &&
n->in(1) == n->in(2));
match(Set dst (MulVL src src));
effect(TEMP tmp);
format %{ "vmulL_$1_neon_same $dst, $src, $src\t# 2L. KILL $tmp" %}
ins_encode %{
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
assert(length_in_bytes == 16, "must be");
__ xtn($tmp$$FloatRegister, __ T2S, $src$$FloatRegister, __ T2D);
__ $2($dst$$FloatRegister, __ T2S, $tmp$$FloatRegister, $tmp$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
instruct vmulL_$1_neon(vReg dst, vReg src1, vReg src2, vReg tmp1, vReg tmp2) %{
predicate(UseSVE == 0 && n->as_MulVL()->has_$1_inputs() &&
n->in(1) != n->in(2));
match(Set dst (MulVL src1 src2));
effect(TEMP tmp1, TEMP tmp2);
format %{ "vmulL_$1_neon $dst, $src1, $src2\t# 2L. KILL $tmp1, $tmp2" %}
ins_encode %{
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
assert(length_in_bytes == 16, "must be");
__ xtn($tmp1$$FloatRegister, __ T2S, $src1$$FloatRegister, __ T2D);
__ xtn($tmp2$$FloatRegister, __ T2S, $src2$$FloatRegister, __ T2D);
__ $2($dst$$FloatRegister, __ T2S, $tmp1$$FloatRegister, $tmp2$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
')dnl
VMUL_L_NEON(int, smullv)
VMUL_L_NEON(uint, umullv)
instruct vmulL_sve(vReg dst_src1, vReg src2) %{
predicate(UseSVE > 0);
predicate(UseSVE == 1 || (UseSVE == 2 && !n->as_MulVL()->has_int_inputs() &&
!n->as_MulVL()->has_uint_inputs()));
match(Set dst_src1 (MulVL dst_src1 src2));
format %{ "vmulL_sve $dst_src1, $dst_src1, $src2" %}
ins_encode %{
@ -756,6 +804,21 @@ instruct vmulL_sve(vReg dst_src1, vReg src2) %{
ins_pipe(pipe_slow);
%}
dnl VMUL_L_SVE2($1, $2 )
dnl VMUL_L_SVE2(kind, sve2_insn )
define(`VMUL_L_SVE2', `dnl
instruct vmulL_$1_sve2(vReg dst, vReg src1, vReg src2) %{
predicate(UseSVE == 2 && n->as_MulVL()->has_$1_inputs());
match(Set dst (MulVL src1 src2));
format %{ "vmulL_$1_sve2 $dst, $src1, $src2" %}
ins_encode %{
__ $2($dst$$FloatRegister, __ D, $src1$$FloatRegister, $src2$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
')dnl
VMUL_L_SVE2(int, sve_smullb)
VMUL_L_SVE2(uint, sve_umullb)
// vector mul - floating-point
BINARY_OP(vmulHF, MulVHF, fmul, sve_fmul, H)
BINARY_OP(vmulF, MulVF, fmul, sve_fmul, S)
@ -4754,6 +4817,31 @@ instruct vblend_sve(vReg dst, vReg src1, vReg src2, pReg pg) %{
ins_pipe(pipe_slow);
%}
// ------------------------------ Vector bitwise blend -------------------------
instruct vbitwise_blend_neon_sve1(vReg src1, vReg src2, vReg dst_src3) %{
predicate(UseSVE < 2 &&
VM_Version::use_neon_for_vector(Matcher::vector_length_in_bytes(n)));
match(Set dst_src3 (VectorBitwiseBlend (Binary src1 src2) dst_src3));
format %{ "vbitwise_blend_neon_sve1 $src1, $src2, $dst_src3" %}
ins_encode %{
uint length_in_bytes = Matcher::vector_length_in_bytes(this);
Assembler::SIMD_Arrangement T = length_in_bytes == 16 ? __ T16B : __ T8B;
__ bsl($dst_src3$$FloatRegister, T, $src2$$FloatRegister, $src1$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
instruct vbitwise_blend_sve2(vReg src1, vReg dst_src2, vReg src3) %{
predicate(UseSVE == 2);
match(Set dst_src2 (VectorBitwiseBlend (Binary src1 dst_src2) src3));
format %{ "vbitwise_blend_sve2 $src1, $dst_src2, $src3" %}
ins_encode %{
__ sve_bsl($dst_src2$$FloatRegister, $src1$$FloatRegister, $src3$$FloatRegister);
%}
ins_pipe(pipe_slow);
%}
// ------------------------------ Vector round ---------------------------------
// vector Math.round

View File

@ -3151,6 +3151,34 @@ public:
_pmull(Vd, Ta, Vn, Vm, Tb);
}
//Vector by element variant of UMULL
void _umullv(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,
SIMD_Arrangement Tb, FloatRegister Vm, SIMD_RegVariant Ts, int lane) {
starti;
int size = (Ta == T4S) ? 0b01 : 0b10;
int q = (Tb == T4H || Tb == T2S) ? 0 : 1;
int h = (size == 0b01) ? ((lane >> 2) & 1) : ((lane >> 1) & 1);
int l = (size == 0b01) ? ((lane >> 1) & 1) : (lane & 1);
assert(Ta == T4S || Ta == T2D, "umull{2}v destination register must have arrangement T4S or T2D");
assert(size == 0b10 ? lane < 4 : lane < 8, "umull{2}v assumes lane < 4 when using half-words and lane < 8 otherwise");
assert(Ts == H ? Vm->encoding() < 16 : Vm->encoding() < 32, "umull{2}v requires Vm to be in range V0..V15 when Ts is H");
f(0, 31), f(q, 30), f(0b101111, 29, 24), f(size, 23, 22), f(l, 21); //f(m, 20);
rf(Vm, 16), f(0b1010, 15, 12), f(h, 11), f(0, 10), rf(Vn, 5), rf(Vd, 0);
}
//Vector by element variant of UMULL
void umullv(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,
SIMD_Arrangement Tb, FloatRegister Vm, SIMD_RegVariant Ts, int lane) {
assert(Ta == T4S ? (Tb == T4H && Ts == H) : (Tb == T2S && Ts == S), "umullv register arrangements must adhere to spec");
_umullv(Vd, Ta, Vn, Tb, Vm, Ts, lane);
}
void umull2v(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn,
SIMD_Arrangement Tb, FloatRegister Vm, SIMD_RegVariant Ts, int lane) {
assert(Ta == T4S ? (Tb == T8H && Ts == H) : (Tb == T4S && Ts == S), "umull2v register arrangements must adhere to spec");
_umullv(Vd, Ta, Vn, Tb, Vm, Ts, lane);
}
void uqxtn(FloatRegister Vd, SIMD_Arrangement Tb, FloatRegister Vn, SIMD_Arrangement Ta) {
starti;
int size_b = (int)Tb >> 1;
@ -4292,14 +4320,31 @@ public:
#undef INSN
// SVE2 bitwise ternary operations
#define INSN(NAME, opc) \
void NAME(FloatRegister Zdn, FloatRegister Zm, FloatRegister Zk) { \
starti; \
f(0b00000100, 31, 24), f(opc, 23, 21), rf(Zm, 16); \
f(0b001110, 15, 10), rf(Zk, 5), rf(Zdn, 0); \
#define INSN(NAME, op1, op2) \
void NAME(FloatRegister Zdn, FloatRegister Zm, FloatRegister Zk) { \
starti; \
f(0b00000100, 31, 24), f(op1, 23, 21), rf(Zm, 16); \
f(0b00111, 15, 11), f(op2, 10), rf(Zk, 5), rf(Zdn, 0); \
}
INSN(sve_eor3, 0b001); // Bitwise exclusive OR of three vectors
INSN(sve_eor3, 0b001, 0b0); // Bitwise exclusive OR of three vectors
INSN(sve_bsl, 0b001, 0b1); // Bitwise select
#undef INSN
// SVE2 widening integer multiply - vector
#define INSN(NAME, is_unsigned, is_top) \
void NAME(FloatRegister Zd, SIMD_RegVariant T, FloatRegister Zn, FloatRegister Zm) { \
starti; \
assert(T != B && T != Q, "invalid size"); \
int op = 0b011100 | (is_unsigned ? 0b10 : 0) | (is_top ? 0b1 : 0); \
f(0b01000101, 31, 24), f(T, 23, 22), f(0, 21), rf(Zm, 16); \
f(op, 15, 10), rf(Zn, 5), rf(Zd, 0); \
}
INSN(sve_umullb, /* is_unsigned */ true, /* is_top */ false); // Unsigned widening multiply of bottom elements
INSN(sve_umullt, /* is_unsigned */ true, /* is_top */ true ); // Unsigned widening multiply of top elements
INSN(sve_smullb, /* is_unsigned */ false, /* is_top */ false); // Signed widening multiply of bottom elements
INSN(sve_smullt, /* is_unsigned */ false, /* is_top */ true ); // Signed widening multiply of top elements
#undef INSN
// SVE2 saturating operations - predicate

View File

@ -452,16 +452,6 @@ int LIR_Assembler::emit_deopt_handler() {
return entry_offset;
}
void LIR_Assembler::add_debug_info_for_branch(address adr, CodeEmitInfo* info) {
_masm->code_section()->relocate(adr, relocInfo::poll_type);
int pc_offset = code_offset();
flush_debug_info(pc_offset);
info->record_debug_info(compilation()->debug_info_recorder(), pc_offset);
if (info->exception_handlers() != nullptr) {
compilation()->add_exception_handlers_for_pco(pc_offset, info->exception_handlers());
}
}
void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) {
assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == r0, "word returns are in r0,");
@ -1334,7 +1324,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
__ bind(not_null);
Register recv = k_RInfo;
__ load_klass(recv, obj);
__ load_klass(recv, obj, rscratch1);
type_profile_helper(mdo, md, data, recv);
} else {
__ cbz(obj, *obj_is_null);
@ -1350,15 +1340,15 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
if (op->fast_check()) {
// get object class
// not a safepoint as obj null check happens earlier
__ load_klass(rscratch1, obj);
__ cmp( rscratch1, k_RInfo);
__ load_klass(rscratch2, obj, rscratch1);
__ cmp( rscratch2, k_RInfo);
__ br(Assembler::NE, *failure_target);
// successful cast, fall through to profile or jump
} else {
// get object class
// not a safepoint as obj null check happens earlier
__ load_klass(klass_RInfo, obj);
__ load_klass(klass_RInfo, obj, rscratch1);
if (k->is_loaded()) {
// See if we get an immediate positive hit
__ ldr(rscratch1, Address(klass_RInfo, int64_t(k->super_check_offset())));
@ -1443,15 +1433,15 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
__ bind(not_null);
Register recv = k_RInfo;
__ load_klass(recv, value);
__ load_klass(recv, value, rscratch1);
type_profile_helper(mdo, md, data, recv);
} else {
__ cbz(value, done);
}
add_debug_info_for_null_check_here(op->info_for_exception());
__ load_klass(k_RInfo, array);
__ load_klass(klass_RInfo, value);
__ load_klass(k_RInfo, array, rscratch1);
__ load_klass(klass_RInfo, value, rscratch1);
// get instance klass (it's already uncompressed)
__ ldr(k_RInfo, Address(k_RInfo, ObjArrayKlass::element_klass_offset()));
@ -1492,12 +1482,12 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
}
void LIR_Assembler::casw(Register addr, Register newval, Register cmpval) {
__ cmpxchg(addr, cmpval, newval, Assembler::word, /* acquire*/ true, /* release*/ true, /* weak*/ false, rscratch1);
__ cmpxchg(addr, cmpval, newval, Assembler::word, memory_order_seq_cst, rscratch1);
__ cset(rscratch1, Assembler::NE);
}
void LIR_Assembler::casl(Register addr, Register newval, Register cmpval) {
__ cmpxchg(addr, cmpval, newval, Assembler::xword, /* acquire*/ true, /* release*/ true, /* weak*/ false, rscratch1);
__ cmpxchg(addr, cmpval, newval, Assembler::xword, memory_order_seq_cst, rscratch1);
__ cset(rscratch1, Assembler::NE);
}
@ -2268,14 +2258,14 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
// an instance type.
if (flags & LIR_OpArrayCopy::type_check) {
if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::dst_objarray)) {
__ load_klass(tmp, dst);
__ load_klass(tmp, dst, rscratch1);
__ ldrw(rscratch1, Address(tmp, in_bytes(Klass::layout_helper_offset())));
__ cmpw(rscratch1, Klass::_lh_neutral_value);
__ br(Assembler::GE, *stub->entry());
}
if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::src_objarray)) {
__ load_klass(tmp, src);
__ load_klass(tmp, src, rscratch1);
__ ldrw(rscratch1, Address(tmp, in_bytes(Klass::layout_helper_offset())));
__ cmpw(rscratch1, Klass::_lh_neutral_value);
__ br(Assembler::GE, *stub->entry());
@ -2329,8 +2319,8 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
__ PUSH(src, dst);
__ load_klass(src, src);
__ load_klass(dst, dst);
__ load_klass(src, src, rscratch1);
__ load_klass(dst, dst, rscratch1);
__ check_klass_subtype_fast_path(src, dst, tmp, &cont, &slow, nullptr);
@ -2354,9 +2344,9 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
assert(flags & mask, "one of the two should be known to be an object array");
if (!(flags & LIR_OpArrayCopy::src_objarray)) {
__ load_klass(tmp, src);
__ load_klass(tmp, src, rscratch1);
} else if (!(flags & LIR_OpArrayCopy::dst_objarray)) {
__ load_klass(tmp, dst);
__ load_klass(tmp, dst, rscratch1);
}
int lh_offset = in_bytes(Klass::layout_helper_offset());
Address klass_lh_addr(tmp, lh_offset);
@ -2382,7 +2372,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
__ uxtw(c_rarg2, length);
assert_different_registers(c_rarg2, dst);
__ load_klass(c_rarg4, dst);
__ load_klass(c_rarg4, dst, rscratch1);
__ ldr(c_rarg4, Address(c_rarg4, ObjArrayKlass::element_klass_offset()));
__ ldrw(c_rarg3, Address(c_rarg4, Klass::super_check_offset_offset()));
__ far_call(RuntimeAddress(copyfunc_addr));
@ -2438,12 +2428,12 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
__ mov_metadata(tmp, default_type->constant_encoding());
if (basic_type != T_OBJECT) {
__ cmp_klass(dst, tmp, rscratch1);
__ cmp_klass(dst, tmp, rscratch1, rscratch2);
__ br(Assembler::NE, halt);
__ cmp_klass(src, tmp, rscratch1);
__ cmp_klass(src, tmp, rscratch1, rscratch2);
__ br(Assembler::EQ, known_ok);
} else {
__ cmp_klass(dst, tmp, rscratch1);
__ cmp_klass(dst, tmp, rscratch1, rscratch2);
__ br(Assembler::EQ, known_ok);
__ cmp(src, dst);
__ br(Assembler::EQ, known_ok);
@ -2518,7 +2508,7 @@ void LIR_Assembler::emit_load_klass(LIR_OpLoadKlass* op) {
add_debug_info_for_null_check_here(info);
}
__ load_klass(result, obj);
__ load_klass(result, obj, rscratch1);
}
void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
@ -2560,7 +2550,7 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
// Fall back to runtime helper to handle the rest at runtime.
__ mov_metadata(recv, known_klass->constant_encoding());
} else {
__ load_klass(recv, recv);
__ load_klass(recv, recv, rscratch1);
}
type_profile_helper(mdo, md, data, recv);
} else {
@ -2646,7 +2636,7 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
#ifdef ASSERT
if (exact_klass != nullptr) {
Label ok;
__ load_klass(tmp, tmp);
__ load_klass(tmp, tmp, rscratch1);
__ mov_metadata(rscratch1, exact_klass->constant_encoding());
__ eor(rscratch1, tmp, rscratch1);
__ cbz(rscratch1, ok);
@ -2659,7 +2649,7 @@ void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {
if (exact_klass != nullptr) {
__ mov_metadata(tmp, exact_klass->constant_encoding());
} else {
__ load_klass(tmp, tmp);
__ load_klass(tmp, tmp, rscratch1);
}
__ ldr(rscratch2, mdo_addr);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2026, 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.
*
@ -52,7 +52,6 @@ friend class ArrayCopyStub;
// Record the type of the receiver in ReceiverTypeData
void type_profile_helper(Register mdo, ciMethodData *md,
ciProfileData *data, Register recv);
void add_debug_info_for_branch(address adr, CodeEmitInfo* info);
void casw(Register addr, Register newval, Register cmpval);
void casl(Register addr, Register newval, Register cmpval);

View File

@ -105,7 +105,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register
} else {
mov(t1, checked_cast<int32_t>(markWord::prototype().value()));
str(t1, Address(obj, oopDesc::mark_offset_in_bytes()));
encode_klass_not_null(t1, klass); // Take care not to kill klass
encode_klass_not_null(t1, klass, t1); // Take care not to kill klass
strw(t1, Address(obj, oopDesc::klass_offset_in_bytes()));
}

View File

@ -824,7 +824,7 @@ OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) {
// load the klass and check the has finalizer flag
Label register_finalizer;
Register t = r5;
__ load_klass(t, r0);
__ load_klass(t, r0, rscratch1);
__ ldrb(t, Address(t, Klass::misc_flags_offset()));
__ tbnz(t, exact_log2(KlassFlags::_misc_has_finalizer), register_finalizer);
__ ret(lr);
@ -947,7 +947,7 @@ OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) {
__ br(Assembler::EQ, is_secondary); // Klass is a secondary superclass
// Klass is a concrete class
__ load_klass(r5, obj);
__ load_klass(r5, obj, rscratch1);
__ ldr(rscratch1, Address(r5, r3));
__ cmp(klass, rscratch1);
__ cset(result, Assembler::EQ);
@ -955,7 +955,7 @@ OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) {
__ bind(is_secondary);
__ load_klass(obj, obj);
__ load_klass(obj, obj, rscratch1);
// This is necessary because I am never in my own secondary_super list.
__ cmp(obj, klass);

View File

@ -167,7 +167,7 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, Register t1,
}
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(t1, obj);
load_klass(t1, obj, rscratch2);
ldrb(t1, Address(t1, Klass::misc_flags_offset()));
tst(t1, KlassFlags::_misc_is_value_based_class);
br(Assembler::NE, slow_path);
@ -204,8 +204,7 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, Register t1,
// Try to lock. Transition lock-bits 0b01 => 0b00
orr(t1_mark, t1_mark, markWord::unlocked_value);
eor(t3_t, t1_mark, markWord::unlocked_value);
cmpxchg(/*addr*/ obj, /*expected*/ t1_mark, /*new*/ t3_t, Assembler::xword,
/*acquire*/ true, /*release*/ false, /*weak*/ false, noreg);
cmpxchg(/*addr*/ obj, /*expected*/ t1_mark, /*new*/ t3_t, Assembler::xword, memory_order_acquire);
br(Assembler::NE, slow_path);
bind(push);
@ -285,8 +284,7 @@ void C2_MacroAssembler::fast_lock(Register obj, Register box, Register t1,
// Try to CAS owner (no owner => current thread's _monitor_owner_id).
ldr(rscratch2, Address(rthread, JavaThread::monitor_owner_id_offset()));
cmpxchg(t2_owner_addr, zr, rscratch2, Assembler::xword, /*acquire*/ true,
/*release*/ false, /*weak*/ false, t3_owner);
cmpxchg(t2_owner_addr, zr, rscratch2, Assembler::xword, memory_order_acquire, t3_owner);
br(Assembler::EQ, monitor_locked);
// Check if recursive.
@ -371,8 +369,7 @@ void C2_MacroAssembler::fast_unlock(Register obj, Register box, Register t1,
// Try to unlock. Transition lock bits 0b00 => 0b01
assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea");
orr(t3_t, t1_mark, markWord::unlocked_value);
cmpxchg(/*addr*/ obj, /*expected*/ t1_mark, /*new*/ t3_t, Assembler::xword,
/*acquire*/ false, /*release*/ true, /*weak*/ false, noreg);
cmpxchg(/*addr*/ obj, /*expected*/ t1_mark, /*new*/ t3_t, Assembler::xword, memory_order_release);
br(Assembler::EQ, unlocked);
bind(push_and_slow_path);
@ -1809,19 +1806,19 @@ void C2_MacroAssembler::neon_reduce_mul_integral(Register dst, BasicType bt,
if (isQ) {
// Multiply the lower half and higher half of vector iteratively.
// vtmp1 = vsrc[8:15]
ins(vtmp1, D, vsrc, 0, 1);
ext(vtmp1, T16B, vsrc, vsrc, 8);
// vtmp1[n] = vsrc[n] * vsrc[n + 8], where n=[0, 7]
mulv(vtmp1, T8B, vtmp1, vsrc);
// vtmp2 = vtmp1[4:7]
ins(vtmp2, S, vtmp1, 0, 1);
ext(vtmp2, T8B, vtmp1, vtmp1, 4);
// vtmp1[n] = vtmp1[n] * vtmp1[n + 4], where n=[0, 3]
mulv(vtmp1, T8B, vtmp2, vtmp1);
} else {
ins(vtmp1, S, vsrc, 0, 1);
ext(vtmp1, T8B, vsrc, vsrc, 4);
mulv(vtmp1, T8B, vtmp1, vsrc);
}
// vtmp2 = vtmp1[2:3]
ins(vtmp2, H, vtmp1, 0, 1);
ext(vtmp2, T8B, vtmp1, vtmp1, 2);
// vtmp2[n] = vtmp1[n] * vtmp1[n + 2], where n=[0, 1]
mulv(vtmp2, T8B, vtmp2, vtmp1);
// dst = vtmp2[0] * isrc * vtmp2[1]
@ -1834,12 +1831,12 @@ void C2_MacroAssembler::neon_reduce_mul_integral(Register dst, BasicType bt,
break;
case T_SHORT:
if (isQ) {
ins(vtmp2, D, vsrc, 0, 1);
ext(vtmp2, T16B, vsrc, vsrc, 8);
mulv(vtmp2, T4H, vtmp2, vsrc);
ins(vtmp1, S, vtmp2, 0, 1);
ext(vtmp1, T8B, vtmp2, vtmp2, 4);
mulv(vtmp1, T4H, vtmp1, vtmp2);
} else {
ins(vtmp1, S, vsrc, 0, 1);
ext(vtmp1, T8B, vsrc, vsrc, 4);
mulv(vtmp1, T4H, vtmp1, vsrc);
}
umov(rscratch1, vtmp1, H, 0);
@ -1851,7 +1848,7 @@ void C2_MacroAssembler::neon_reduce_mul_integral(Register dst, BasicType bt,
break;
case T_INT:
if (isQ) {
ins(vtmp1, D, vsrc, 0, 1);
ext(vtmp1, T16B, vsrc, vsrc, 8);
mulv(vtmp1, T2S, vtmp1, vsrc);
} else {
vtmp1 = vsrc;
@ -1907,19 +1904,19 @@ void C2_MacroAssembler::neon_reduce_mul_fp(FloatRegister dst, BasicType bt,
break;
case T_FLOAT:
fmuls(dst, fsrc, vsrc);
ins(vtmp, S, vsrc, 0, 1);
ext(vtmp, T8B, vsrc, vsrc, 4);
fmuls(dst, dst, vtmp);
if (isQ) {
ins(vtmp, S, vsrc, 0, 2);
ext(vtmp, T16B, vsrc, vsrc, 8);
fmuls(dst, dst, vtmp);
ins(vtmp, S, vsrc, 0, 3);
ext(vtmp, T16B, vsrc, vsrc, 12);
fmuls(dst, dst, vtmp);
}
break;
case T_DOUBLE:
assert(isQ, "unsupported");
fmuld(dst, fsrc, vsrc);
ins(vtmp, D, vsrc, 0, 1);
ext(vtmp, T16B, vsrc, vsrc, 8);
fmuld(dst, dst, vtmp);
break;
default:
@ -2731,7 +2728,8 @@ void C2_MacroAssembler::reconstruct_frame_pointer(Register rtmp) {
void C2_MacroAssembler::select_from_two_vectors_neon(FloatRegister dst, FloatRegister src1,
FloatRegister src2, FloatRegister index,
FloatRegister tmp, unsigned vector_length_in_bytes) {
assert_different_registers(dst, src1, src2, tmp);
assert_different_registers(src2, tmp);
assert_different_registers(index, tmp);
SIMD_Arrangement size = vector_length_in_bytes == 16 ? T16B : T8B;
if (vector_length_in_bytes == 16) {
@ -2760,7 +2758,8 @@ void C2_MacroAssembler::select_from_two_vectors_sve(FloatRegister dst, FloatRegi
FloatRegister src2, FloatRegister index,
FloatRegister tmp, SIMD_RegVariant T,
unsigned vector_length_in_bytes) {
assert_different_registers(dst, src1, src2, index, tmp);
assert_different_registers(src2, tmp);
assert_different_registers(index, tmp);
if (vector_length_in_bytes == 8) {
// We need to fit both the source vectors (src1, src2) in a single vector register because the
@ -2787,7 +2786,8 @@ void C2_MacroAssembler::select_from_two_vectors(FloatRegister dst, FloatRegister
FloatRegister tmp, BasicType bt,
unsigned vector_length_in_bytes) {
assert_different_registers(dst, src1, src2, index, tmp);
assert_different_registers(dst, src1, src2, tmp);
assert_different_registers(index, tmp);
// The cases that can reach this method are -
// - UseSVE = 0/1, vector_length_in_bytes = 8 or 16, excluding double and long types

View File

@ -120,11 +120,7 @@ char* CompressedKlassPointers::reserve_address_space_for_compressed_classes(size
return result;
}
bool CompressedKlassPointers::check_klass_decode_mode(address base, int shift, const size_t range) {
return MacroAssembler::check_klass_decode_mode(base, shift, range);
}
bool CompressedKlassPointers::set_klass_decode_mode() {
void CompressedKlassPointers::initialize_pd() {
const size_t range = klass_range_end() - base();
return MacroAssembler::set_klass_decode_mode(_base, _shift, range);
MacroAssembler::initialize_klass_decode_mode(_base, _shift, range);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2026, 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.
*
@ -66,7 +66,6 @@
public:
enum {
pc_return_offset = 0,
// All frames
link_offset = 0,
return_addr_offset = 1,
@ -187,8 +186,6 @@
// deoptimization support
void interpreter_frame_set_last_sp(intptr_t* sp);
static jint interpreter_frame_expression_stack_direction() { return -1; }
// returns the sending frame, without applying any barriers
inline frame sender_raw(RegisterMap* map) const;

View File

@ -283,7 +283,7 @@ instruct g1CompareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP
RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
RegSet::of($res$$Register) /* no_preserve */);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
false /* acquire */, true /* release */, false /* weak */, $res$$Register);
memory_order_release, $res$$Register);
write_barrier_post(masm, this,
$mem$$Register /* store_addr */,
$newval$$Register /* new_val */,
@ -316,7 +316,7 @@ instruct g1CompareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iRe
RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
RegSet::of($res$$Register) /* no_preserve */);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
true /* acquire */, true /* release */, false /* weak */, $res$$Register);
memory_order_seq_cst, $res$$Register);
write_barrier_post(masm, this,
$mem$$Register /* store_addr */,
$newval$$Register /* new_val */,
@ -346,7 +346,7 @@ instruct g1CompareAndExchangeN(iRegNNoSp res, indirect mem, iRegN oldval, iRegN
RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
RegSet::of($res$$Register) /* no_preserve */);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word,
false /* acquire */, true /* release */, false /* weak */, $res$$Register);
memory_order_release, $res$$Register);
__ decode_heap_oop($tmp1$$Register, $newval$$Register);
write_barrier_post(masm, this,
$mem$$Register /* store_addr */,
@ -377,7 +377,7 @@ instruct g1CompareAndExchangeNAcq(iRegNNoSp res, indirect mem, iRegN oldval, iRe
RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
RegSet::of($res$$Register) /* no_preserve */);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word,
true /* acquire */, true /* release */, false /* weak */, $res$$Register);
memory_order_seq_cst, $res$$Register);
__ decode_heap_oop($tmp1$$Register, $newval$$Register);
write_barrier_post(masm, this,
$mem$$Register /* store_addr */,
@ -409,8 +409,7 @@ instruct g1CompareAndSwapP(iRegINoSp res, indirect mem, iRegP newval, iRegPNoSp
$tmp2$$Register /* tmp2 */,
RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
RegSet::of($res$$Register) /* no_preserve */);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
false /* acquire */, true /* release */, false /* weak */, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_release);
__ cset($res$$Register, Assembler::EQ);
write_barrier_post(masm, this,
$mem$$Register /* store_addr */,
@ -442,8 +441,7 @@ instruct g1CompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP newval, iRegPNo
$tmp2$$Register /* tmp2 */,
RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
RegSet::of($res$$Register) /* no_preserve */);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
true /* acquire */, true /* release */, false /* weak */, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, memory_order_seq_cst);
__ cset($res$$Register, Assembler::EQ);
write_barrier_post(masm, this,
$mem$$Register /* store_addr */,
@ -475,8 +473,7 @@ instruct g1CompareAndSwapN(iRegINoSp res, indirect mem, iRegN newval, iRegPNoSp
$tmp3$$Register /* tmp2 */,
RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
RegSet::of($res$$Register) /* no_preserve */);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word,
false /* acquire */, true /* release */, false /* weak */, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_release);
__ cset($res$$Register, Assembler::EQ);
__ decode_heap_oop($tmp1$$Register, $newval$$Register);
write_barrier_post(masm, this,
@ -509,8 +506,7 @@ instruct g1CompareAndSwapNAcq(iRegINoSp res, indirect mem, iRegN newval, iRegPNo
$tmp3$$Register /* tmp2 */,
RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
RegSet::of($res$$Register) /* no_preserve */);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word,
true /* acquire */, true /* release */, false /* weak */, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, memory_order_seq_cst);
__ cset($res$$Register, Assembler::EQ);
__ decode_heap_oop($tmp1$$Register, $newval$$Register);
write_barrier_post(masm, this,

View File

@ -151,7 +151,7 @@ instruct g1CompareAndExchangeP$1(iRegPNoSp res, indirect mem, iRegP oldval, iReg
RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
RegSet::of($res$$Register) /* no_preserve */);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
$3 /* acquire */, true /* release */, false /* weak */, $res$$Register);
ifelse($1,Acq,memory_order_seq_cst,memory_order_release), $res$$Register);
write_barrier_post(masm, this,
$mem$$Register /* store_addr */,
$newval$$Register /* new_val */,
@ -160,8 +160,8 @@ instruct g1CompareAndExchangeP$1(iRegPNoSp res, indirect mem, iRegP oldval, iReg
%}
ins_pipe(pipe_slow);
%}')dnl
CAEP_INSN(,,false)
CAEP_INSN(Acq,_acq,true)
CAEP_INSN(,)
CAEP_INSN(Acq,_acq)
dnl
define(`CAEN_INSN',
`
@ -185,7 +185,7 @@ instruct g1CompareAndExchangeN$1(iRegNNoSp res, indirect mem, iRegN oldval, iReg
RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
RegSet::of($res$$Register) /* no_preserve */);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word,
$3 /* acquire */, true /* release */, false /* weak */, $res$$Register);
ifelse($1,Acq,memory_order_seq_cst,memory_order_release), $res$$Register);
__ decode_heap_oop($tmp1$$Register, $newval$$Register);
write_barrier_post(masm, this,
$mem$$Register /* store_addr */,
@ -195,8 +195,8 @@ instruct g1CompareAndExchangeN$1(iRegNNoSp res, indirect mem, iRegN oldval, iReg
%}
ins_pipe(pipe_slow);
%}')dnl
CAEN_INSN(,,false)
CAEN_INSN(Acq,_acq,true)
CAEN_INSN(,)
CAEN_INSN(Acq,_acq)
dnl
define(`CASP_INSN',
`
@ -221,8 +221,7 @@ instruct g1CompareAndSwapP$1(iRegINoSp res, indirect mem, iRegP newval, iRegPNoS
$tmp2$$Register /* tmp2 */,
RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
RegSet::of($res$$Register) /* no_preserve */);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword,
$3 /* acquire */, true /* release */, false /* weak */, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::xword, ifelse($1,Acq,memory_order_seq_cst,memory_order_release));
__ cset($res$$Register, Assembler::EQ);
write_barrier_post(masm, this,
$mem$$Register /* store_addr */,
@ -232,8 +231,8 @@ instruct g1CompareAndSwapP$1(iRegINoSp res, indirect mem, iRegP newval, iRegPNoS
%}
ins_pipe(pipe_slow);
%}')dnl
CASP_INSN(,,false)
CASP_INSN(Acq,_acq,true)
CASP_INSN(,)
CASP_INSN(Acq,_acq)
dnl
define(`CASN_INSN',
`
@ -258,8 +257,7 @@ instruct g1CompareAndSwapN$1(iRegINoSp res, indirect mem, iRegN newval, iRegPNoS
$tmp3$$Register /* tmp2 */,
RegSet::of($mem$$Register, $oldval$$Register, $newval$$Register) /* preserve */,
RegSet::of($res$$Register) /* no_preserve */);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word,
$3 /* acquire */, true /* release */, false /* weak */, noreg);
__ cmpxchg($mem$$Register, $oldval$$Register, $newval$$Register, Assembler::word, ifelse($1,Acq,memory_order_seq_cst,memory_order_release));
__ cset($res$$Register, Assembler::EQ);
__ decode_heap_oop($tmp1$$Register, $newval$$Register);
write_barrier_post(masm, this,
@ -270,8 +268,8 @@ instruct g1CompareAndSwapN$1(iRegINoSp res, indirect mem, iRegN newval, iRegPNoS
%}
ins_pipe(pipe_slow);
%}')dnl
CASN_INSN(,,false)
CASN_INSN(Acq,_acq,true)
CASN_INSN(,)
CASN_INSN(Acq,_acq)
dnl
define(`XCHGP_INSN',
`

View File

@ -389,8 +389,8 @@ void BarrierSetAssembler::check_oop(MacroAssembler* masm, Register obj, Register
__ cbnz(tmp1, error);
// make sure klass is 'reasonable', which is not zero.
__ load_klass(obj, obj); // get klass
__ cbz(obj, error); // if klass is null it is broken
__ load_narrow_klass(tmp1, obj); // get klass
__ cbz(tmp1, error); // if klass is null it is broken
}
void BarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj, Register tmp, Label& slow_path) {

View File

@ -124,14 +124,13 @@ public:
}
};
// The first instruction of the nmethod entry barrier is an ldr (literal)
// The first instruction of the nmethod entry barrier is an ldrw (literal)
// instruction. Verify that it's really there, so the offsets are not skewed.
bool NativeNMethodBarrier::check_barrier(err_msg& msg) const {
uint32_t* addr = (uint32_t*) instruction_address();
uint32_t inst = *addr;
if ((inst & 0xff000000) != 0x18000000) {
msg.print("Nmethod entry barrier did not start with ldr (literal) as expected. "
"Addr: " PTR_FORMAT " Code: " UINT32_FORMAT, p2i(addr), inst);
NativeInstruction* ni = nativeInstruction_at(instruction_address());
if (!ni->is_ldrw_gpr_literal()) {
msg.print("Nmethod entry barrier did not start with ldrw (literal) as expected. "
"Addr: " PTR_FORMAT " Code: " UINT32_FORMAT, p2i(instruction_address()), ni->encoding());
return false;
}
return true;

View File

@ -420,6 +420,32 @@ void ShenandoahBarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembl
__ bind(done);
}
void ShenandoahBarrierSetAssembler::check_oop(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2, Label& L_error) {
// Check if the oop is in the right area of memory
__ mov(tmp2, (intptr_t) Universe::verify_oop_mask());
__ andr(tmp1, obj, tmp2);
__ mov(tmp2, (intptr_t) Universe::verify_oop_bits());
// Compare tmp1 and tmp2. We don't use a compare
// instruction here because the flags register is live.
__ eor(tmp1, tmp1, tmp2);
__ cbnz(tmp1, L_error);
// This routine is sometimes called before applying GC barriers.
// With +COH, loading the klass may end up loading forwarding pointer instead.
Label L_skip;
if (UseCompactObjectHeaders) {
Address gc_state(rthread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
__ ldrb(tmp1, gc_state);
__ tbnz(tmp1, ShenandoahHeap::HAS_FORWARDED_BITPOS, L_skip);
}
// Make sure klass is 'reasonable', which is not zero.
__ load_narrow_klass(tmp1, obj);
__ cbz(tmp1, L_error);
__ bind(L_skip);
}
void ShenandoahBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
Register start, Register count, Register scratch) {
assert(ShenandoahCardBarrier, "Should have been checked by caller");
@ -456,79 +482,38 @@ void ShenandoahBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssemb
#define __ ce->masm()->
void ShenandoahBarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub) {
ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
// At this point we know that marking is in progress.
// If do_load() is true then we have to emit the
// load of the previous value; otherwise it has already
// been loaded into _pre_val.
void ShenandoahBarrierSetAssembler::keepalive_barrier_c1_stub(LIR_Assembler* ce, ShenandoahKeepaliveBarrierStub* stub) {
__ bind(*stub->entry());
assert(stub->pre_val()->is_register(), "Precondition.");
ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
Register pre_val_reg = stub->pre_val()->as_register();
Register obj = stub->obj()->as_register();
if (stub->do_load()) {
ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /*wide*/);
ce->mem2reg(stub->addr(), stub->obj(), T_OBJECT, lir_patch_none, nullptr, /* wide = */ false);
}
__ cbz(pre_val_reg, *stub->continuation());
ce->store_parameter(stub->pre_val()->as_register(), 0);
__ far_call(RuntimeAddress(bs->pre_barrier_c1_runtime_code_blob()->code_begin()));
__ cbz(obj, *stub->continuation());
ce->store_parameter(obj, 0);
__ far_call(RuntimeAddress(bs->keepalive_barrier_stub()));
__ b(*stub->continuation());
}
void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub) {
ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
void ShenandoahBarrierSetAssembler::load_reference_barrier_c1_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub) {
__ bind(*stub->entry());
DecoratorSet decorators = stub->decorators();
bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators);
bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators);
bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators);
bool is_native = ShenandoahBarrierSet::is_native_access(decorators);
ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
Register obj = stub->obj()->as_register();
Register res = stub->result()->as_register();
Register addr = stub->addr()->as_pointer_register();
Register tmp1 = stub->tmp1()->as_register();
Register tmp2 = stub->tmp2()->as_register();
Register slow_result = stub->slow_result()->as_register();
assert_different_registers(obj, addr, slow_result);
assert(slow_result == r0, "C1 must know about our slow call result register");
assert(res == r0, "result must arrive in r0");
if (res != obj) {
__ mov(res, obj);
}
if (is_strong) {
// Check for object in cset.
if (AOTCodeCache::is_on_for_dump()) {
__ lea(tmp2, ExternalAddress(AOTRuntimeConstants::cset_base_address()));
__ ldr(tmp2, Address(tmp2));
__ lea(tmp1, ExternalAddress(AOTRuntimeConstants::grain_shift_address()));
__ ldrw(tmp1, Address(tmp1));
__ lsrv(tmp1, res, tmp1);
} else {
__ mov(tmp2, ShenandoahHeap::in_cset_fast_test_addr());
__ lsr(tmp1, res, ShenandoahHeapRegion::region_size_bytes_shift_jint());
}
__ ldrb(tmp2, Address(tmp2, tmp1));
__ cbz(tmp2, *stub->continuation());
}
ce->store_parameter(res, 0);
ce->store_parameter(obj, 0);
ce->store_parameter(addr, 1);
if (is_strong) {
if (is_native) {
__ far_call(RuntimeAddress(bs->load_reference_barrier_strong_native_rt_code_blob()->code_begin()));
} else {
__ far_call(RuntimeAddress(bs->load_reference_barrier_strong_rt_code_blob()->code_begin()));
}
} else if (is_weak) {
__ far_call(RuntimeAddress(bs->load_reference_barrier_weak_rt_code_blob()->code_begin()));
} else {
assert(is_phantom, "only remaining strength");
__ far_call(RuntimeAddress(bs->load_reference_barrier_phantom_rt_code_blob()->code_begin()));
__ far_call(RuntimeAddress(bs->load_reference_barrier_stub(stub->decorators())));
if (obj != slow_result) {
__ mov(obj, slow_result);
}
__ b(*stub->continuation());
@ -538,89 +523,27 @@ void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assemble
#define __ sasm->
void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
__ prologue("shenandoah_pre_barrier", false);
// arg0 : previous value of memory
BarrierSet* bs = BarrierSet::barrier_set();
const Register pre_val = r0;
const Register thread = rthread;
const Register tmp = rscratch1;
Address queue_index(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset()));
Address buffer(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset()));
Label done;
Label runtime;
// Is marking still active?
Address gc_state(thread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
__ ldrb(tmp, gc_state);
__ tbz(tmp, ShenandoahHeap::MARKING_BITPOS, done);
// Can we store original value in the thread's buffer?
__ ldr(tmp, queue_index);
__ cbz(tmp, runtime);
__ sub(tmp, tmp, wordSize);
__ str(tmp, queue_index);
__ ldr(rscratch2, buffer);
__ add(tmp, tmp, rscratch2);
__ load_parameter(0, rscratch2);
__ str(rscratch2, Address(tmp, 0));
__ b(done);
__ bind(runtime);
__ push_call_clobbered_registers();
__ load_parameter(0, pre_val);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_pre), pre_val);
__ pop_call_clobbered_registers();
__ bind(done);
void ShenandoahBarrierSetAssembler::keepalive_barrier_c1_runtime_stub(StubAssembler* sasm) {
__ prologue("shenandoah_keepalive_barrier", false);
const Register tmp_obj = r0;
const Register tmp1 = r1;
const Register tmp2 = r2;
__ push(RegSet::of(tmp1, tmp2, tmp_obj), sp);
__ load_parameter(0, tmp_obj);
satb_barrier(sasm, noreg, tmp_obj, rthread, tmp1, tmp2);
__ pop(RegSet::of(tmp1, tmp2, tmp_obj), sp);
__ epilogue();
}
void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, DecoratorSet decorators) {
void ShenandoahBarrierSetAssembler::load_reference_barrier_c1_runtime_stub(StubAssembler* sasm, DecoratorSet decorators) {
__ prologue("shenandoah_load_reference_barrier", false);
// arg0 : object to be resolved
__ push_call_clobbered_registers();
__ load_parameter(0, r0);
__ load_parameter(1, r1);
bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators);
bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators);
bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators);
bool is_native = ShenandoahBarrierSet::is_native_access(decorators);
if (is_strong) {
if (is_native) {
__ lea(lr, RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong)));
} else {
if (UseCompressedOops) {
__ lea(lr, RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong_narrow)));
} else {
__ lea(lr, RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong)));
}
}
} else if (is_weak) {
assert(!is_native, "weak must not be called off-heap");
if (UseCompressedOops) {
__ lea(lr, RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak_narrow)));
} else {
__ lea(lr, RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak)));
}
} else {
assert(is_phantom, "only remaining strength");
assert(is_native, "phantom must only be called off-heap");
__ lea(lr, RuntimeAddress(CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom)));
}
__ blr(lr);
__ mov(rscratch1, r0);
__ pop_call_clobbered_registers();
__ mov(r0, rscratch1);
const Register tmp_obj = r0;
const Register tmp_addr = r1;
__ push(RegSet::of(tmp_addr), sp);
__ load_parameter(0, tmp_obj);
__ load_parameter(1, tmp_addr);
load_reference_barrier(sasm, tmp_obj, Address(tmp_addr, 0), decorators);
__ pop(RegSet::of(tmp_addr), sp);
__ epilogue();
}
@ -700,8 +623,14 @@ void ShenandoahBarrierSetAssembler::compare_and_set_c2(const MachNode* node, Mac
ShenandoahBarrierStubC2::load_store_pre(masm, node, addr, tmp1, tmp2, tmp3, narrow);
atomic_memory_order order = acquire ? memory_order_seq_cst : memory_order_release;
// CAS!
__ cmpxchg(addr, oldval, newval, op_size, acquire, /* release */ true, weak, exchange ? res : noreg);
if (weak) {
__ cmpxchg_weak(addr, oldval, newval, op_size, order, exchange ? res : noreg);
} else {
__ cmpxchg(addr, oldval, newval, op_size, order, exchange ? res : noreg);
}
// If we need a boolean result out of CAS, set the flag appropriately and promote the result.
if (!exchange) {

View File

@ -32,7 +32,7 @@
#include "gc/shenandoah/shenandoahBarrierSet.hpp"
#ifdef COMPILER1
class LIR_Assembler;
class ShenandoahPreBarrierStub;
class ShenandoahKeepaliveBarrierStub;
class ShenandoahLoadReferenceBarrierStub;
class StubAssembler;
#endif
@ -74,12 +74,14 @@ public:
Register obj, Register tmp, Label& slowpath);
virtual void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj,
Register tmp, Label& slow_path);
virtual void check_oop(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2, Label& L_error);
#ifdef COMPILER1
void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, DecoratorSet decorators);
void keepalive_barrier_c1_stub(LIR_Assembler* ce, ShenandoahKeepaliveBarrierStub* stub);
void keepalive_barrier_c1_runtime_stub(StubAssembler* sasm);
void load_reference_barrier_c1_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
void load_reference_barrier_c1_runtime_stub(StubAssembler* sasm, DecoratorSet decorators);
#endif
#ifdef COMPILER2

View File

@ -283,10 +283,7 @@ void ZBarrierSetAssembler::store_barrier_medium(MacroAssembler* masm,
// If we get this far, we know there is a young raw null value in the field.
__ relocate(barrier_Relocation::spec(), ZBarrierRelocationFormatStoreGoodBeforeMov);
__ movzw(rtmp1, barrier_Relocation::unpatched);
__ cmpxchg(rtmp2, zr, rtmp1,
Assembler::xword,
false /* acquire */, false /* release */, true /* weak */,
rtmp3);
__ cmpxchg_weak(rtmp2, zr, rtmp1, Assembler::xword, memory_order_relaxed, rtmp3);
__ br(Assembler::NE, slow_path);
__ bind(slow_path_continuation);
@ -1388,9 +1385,8 @@ void ZBarrierSetAssembler::check_oop(MacroAssembler* masm, Register obj, Registe
__ bind(check_oop);
// make sure klass is 'reasonable', which is not zero.
__ load_klass(tmp1, obj); // get klass
__ tst(tmp1, tmp1);
__ br(Assembler::EQ, error); // if klass is null it is broken
__ load_narrow_klass(tmp1, obj); // get narrow klass
__ cbz(tmp1, error); // if klass is null it is broken
__ bind(check_zaddress);
// Check if the oop is in the right area of memory

View File

@ -207,8 +207,7 @@ instruct zCompareAndSwapP(iRegINoSp res, indirect mem, iRegP oldval, iRegP newva
Address ref_addr($mem$$Register);
z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, rscratch2, true /* is_atomic */);
z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register);
__ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword,
false /* acquire */, true /* release */, false /* weak */, noreg);
__ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword, memory_order_release);
__ cset($res$$Register, Assembler::EQ);
%}
@ -231,8 +230,7 @@ instruct zCompareAndSwapPAcq(iRegINoSp res, indirect mem, iRegP oldval, iRegP ne
Address ref_addr($mem$$Register);
z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, rscratch2, true /* is_atomic */);
z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register);
__ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword,
true /* acquire */, true /* release */, false /* weak */, noreg);
__ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword, memory_order_seq_cst);
__ cset($res$$Register, Assembler::EQ);
%}
@ -255,7 +253,7 @@ instruct zCompareAndExchangeP(iRegPNoSp res, indirect mem, iRegP oldval, iRegP n
z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, rscratch2, true /* is_atomic */);
z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register);
__ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword,
false /* acquire */, true /* release */, false /* weak */, $res$$Register);
memory_order_release, $res$$Register);
z_uncolor(masm, this, $res$$Register);
%}
@ -278,7 +276,7 @@ instruct zCompareAndExchangePAcq(iRegPNoSp res, indirect mem, iRegP oldval, iReg
z_store_barrier(masm, this, ref_addr, $newval$$Register, $newval_tmp$$Register, rscratch2, true /* is_atomic */);
z_color(masm, this, $oldval_tmp$$Register, $oldval$$Register);
__ cmpxchg($mem$$Register, $oldval_tmp$$Register, $newval_tmp$$Register, Assembler::xword,
true /* acquire */, true /* release */, false /* weak */, $res$$Register);
memory_order_seq_cst, $res$$Register);
z_uncolor(masm, this, $res$$Register);
%}

View File

@ -61,7 +61,9 @@ const bool CCallingConventionRequiresIntsAsLongs = false;
// evidence that it's worth doing.
#define DEOPTIMIZE_WHEN_PATCHING
#if !defined(_WINDOWS)
#define SUPPORT_RESERVED_STACK_AREA
#endif
#if defined(__APPLE__) || defined(_WIN64)
#define R18_RESERVED

View File

@ -48,7 +48,7 @@ define_pd_global(intx, OptoLoopAlignment, 16);
// stack if compiled for unix and LP64. To pass stack overflow tests we need
// 20 shadow pages.
#define DEFAULT_STACK_SHADOW_PAGES (20 DEBUG_ONLY(+5))
#define DEFAULT_STACK_RESERVED_PAGES (1)
#define DEFAULT_STACK_RESERVED_PAGES (NOT_WINDOWS(1) WINDOWS_ONLY(0))
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES

View File

@ -1403,7 +1403,7 @@ void InterpreterMacroAssembler::profile_obj_type(Register obj, const Address& md
b(next);
bind(update);
load_klass(obj, obj);
load_klass(obj, obj, rscratch1);
ldr(rscratch1, mdo_addr);
eor(obj, obj, rscratch1);

View File

@ -25,6 +25,7 @@
#include "asm/assembler.hpp"
#include "asm/assembler.inline.hpp"
#include "cds/archiveBuilder.hpp"
#include "ci/ciEnv.hpp"
#include "code/compiledIC.hpp"
#include "compiler/compileTask.hpp"
@ -622,20 +623,18 @@ void MacroAssembler::set_last_Java_frame(Register last_java_sp,
}
}
static inline bool target_needs_far_branch(address addr) {
bool MacroAssembler::target_needs_far_branch(address addr) {
if (AOTCodeCache::is_on_for_dump()) {
return true;
}
// codecache size <= 128M
if (!MacroAssembler::far_branches()) {
if (!far_branches()) {
return false;
}
// codecache size > 240M
if (MacroAssembler::codestub_branch_needs_far_jump()) {
return true;
if (CodeCache::is_non_nmethod(addr) &&
CodeCache::max_distance_to_non_nmethod() <= branch_range) {
return false;
}
// codecache size: 128M..240M
return !CodeCache::is_non_nmethod(addr);
return true;
}
void MacroAssembler::far_call(Address entry, Register tmp) {
@ -2231,8 +2230,7 @@ void MacroAssembler::profile_receiver_type(Register recv, Register mdp, int mdp_
// offset is no longer needed after the address is computed.
lea(rscratch2, Address(mdp, offset));
cmpxchg(/*addr*/ rscratch2, /*expected*/ zr, /*new*/ recv, Assembler::xword,
/*acquire*/ false, /*release*/ false, /*weak*/ true, noreg);
cmpxchg_weak(/*addr*/ rscratch2, /*expected*/ zr, /*new*/ recv, Assembler::xword, memory_order_relaxed);
// CAS success means the slot now has the receiver we want. CAS failure means
// something had claimed the slot concurrently: it can be the same receiver we want,
@ -3494,9 +3492,33 @@ void MacroAssembler::reinit_heapbase()
void MacroAssembler::cmpxchg(Register addr, Register expected,
Register new_val,
enum operand_size size,
bool acquire, bool release,
enum atomic_memory_order order,
bool weak,
Register result) {
bool acquire, release;
switch (order) {
case memory_order_relaxed:
acquire = false;
release = false;
break;
case memory_order_acquire:
acquire = true;
release = false;
break;
case memory_order_release:
acquire = false;
release = true;
break;
case memory_order_acq_rel:
case memory_order_seq_cst:
acquire = true;
release = true;
break;
default:
ShouldNotReachHere();
}
if (result == noreg) result = rscratch1;
BLOCK_COMMENT("cmpxchg {");
if (UseLSE) {
@ -5074,7 +5096,7 @@ void MacroAssembler::load_method_holder(Register holder, Register method) {
ldr(holder, Address(holder, ConstantPool::pool_holder_offset())); // InstanceKlass*
}
// Loads the obj's Klass* into dst.
// Loads the obj's narrow Klass from a compact object header (+COH) into dst.
// Preserves all registers (incl src, rscratch1 and rscratch2).
// Input:
// src - the oop we want to load the klass from.
@ -5085,13 +5107,18 @@ void MacroAssembler::load_narrow_klass_compact(Register dst, Register src) {
lsr(dst, dst, markWord::klass_shift);
}
void MacroAssembler::load_klass(Register dst, Register src) {
// Loads the obj's narrow Klass from any header (compact or not) into dst.
void MacroAssembler::load_narrow_klass(Register dst, Register src) {
if (UseCompactObjectHeaders) {
load_narrow_klass_compact(dst, src);
} else {
ldrw(dst, Address(src, oopDesc::klass_offset_in_bytes()));
}
decode_klass_not_null(dst);
}
void MacroAssembler::load_klass(Register dst, Register src, Register tmp) {
load_narrow_klass(dst, src);
decode_klass_not_null(dst, dst, tmp);
}
void MacroAssembler::restore_cpu_control_state_after_jni(Register tmp1, Register tmp2) {
@ -5141,8 +5168,8 @@ void MacroAssembler::load_mirror(Register dst, Register method, Register tmp1, R
resolve_oop_handle(dst, tmp1, tmp2);
}
void MacroAssembler::cmp_klass(Register obj, Register klass, Register tmp) {
assert_different_registers(obj, klass, tmp);
void MacroAssembler::cmp_klass(Register obj, Register klass, Register tmp, Register tmp2) {
assert_different_registers(obj, klass, tmp, tmp2);
if (UseCompactObjectHeaders) {
load_narrow_klass_compact(tmp, obj);
} else {
@ -5158,7 +5185,7 @@ void MacroAssembler::cmp_klass(Register obj, Register klass, Register tmp) {
cmpw(klass, tmp);
return;
}
decode_klass_not_null(tmp);
decode_klass_not_null(tmp, tmp, tmp2);
cmp(klass, tmp);
}
@ -5173,11 +5200,11 @@ void MacroAssembler::cmp_klasses_from_objects(Register obj1, Register obj2, Regi
cmpw(tmp1, tmp2);
}
void MacroAssembler::store_klass(Register dst, Register src) {
void MacroAssembler::store_klass(Register dst, Register src, Register tmp) {
// FIXME: Should this be a store release? concurrent gcs assumes
// klass length is valid if klass field is not null.
assert(!UseCompactObjectHeaders, "not with compact headers");
encode_klass_not_null(src);
encode_klass_not_null(src, src, tmp);
strw(src, Address(dst, oopDesc::klass_offset_in_bytes()));
}
@ -5330,8 +5357,6 @@ MacroAssembler::KlassDecodeMode MacroAssembler::klass_decode_mode() {
}
MacroAssembler::KlassDecodeMode MacroAssembler::klass_decode_mode(address base, int shift, const size_t range) {
// KlassDecodeMode shouldn't be set already.
assert(_klass_decode_mode == KlassDecodeNone, "set once");
if (base == nullptr) {
return KlassDecodeZero;
@ -5351,148 +5376,128 @@ MacroAssembler::KlassDecodeMode MacroAssembler::klass_decode_mode(address base,
return KlassDecodeMovk;
}
// No valid encoding.
return KlassDecodeNone;
return KlassDecodeFallback;
}
// Check if one of the above decoding modes will work for given base, shift and range.
bool MacroAssembler::check_klass_decode_mode(address base, int shift, const size_t range) {
return klass_decode_mode(base, shift, range) != KlassDecodeNone;
}
bool MacroAssembler::set_klass_decode_mode(address base, int shift, const size_t range) {
void MacroAssembler::initialize_klass_decode_mode(address base, int shift, const size_t range) {
// KlassDecodeMode shouldn't be set already.
assert(_klass_decode_mode == KlassDecodeNone, "set once");
_klass_decode_mode = klass_decode_mode(base, shift, range);
return _klass_decode_mode != KlassDecodeNone;
log_info(metaspace)("Klass Decode Mode: %d", (int)_klass_decode_mode);
}
static Register pick_different_tmp(Register dst, Register src) {
auto tmps = RegSet::of(r0, r1, r2) - RegSet::of(src, dst);
return *tmps.begin();
void MacroAssembler::encode_klass_not_null(Register dst, Register src, Register tmp) {
emit_encode_klass_not_null(dst, src, tmp, CompressedKlassPointers::base(),
CompressedKlassPointers::shift(), klass_decode_mode());
}
void MacroAssembler::encode_klass_not_null_for_aot(Register dst, Register src) {
// we have to load the klass base from the AOT constants area but
// not the shift because it is not allowed to change
int shift = CompressedKlassPointers::shift();
assert(shift >= 0 && shift <= CompressedKlassPointers::max_shift(), "unexpected compressed klass shift!");
if (dst != src) {
// we can load the base into dst, subtract it formthe src and shift down
lea(dst, ExternalAddress(CompressedKlassPointers::base_addr()));
ldr(dst, dst);
sub(dst, src, dst);
lsr(dst, dst, shift);
} else {
// we need an extra register in order to load the coop base
Register tmp = pick_different_tmp(dst, src);
RegSet regs = RegSet::of(tmp);
push(regs, sp);
void MacroAssembler::emit_encode_klass_not_null(Register dst, Register src, Register tmp,
address base, int shift, KlassDecodeMode decode_mode) {
assert_different_registers(tmp, src);
assert(tmp != noreg, "valid tmp required");
if (AOTCodeCache::is_on_for_dump()) {
// We are generating code during AOT buildup that will run in *future* processes
// with likely different encoding settings. Therefore, we have to load the
// encoding base dynamically, we cannot just bake it in as immediate.
// Note that we only need to do this for base. The encoding shift would be the
// same between build time and runtime: the standard precomputed shift.
assert(shift == ArchiveBuilder::precomputed_narrow_klass_shift(), "unexpected compressed klass shift!");
lea(tmp, ExternalAddress(CompressedKlassPointers::base_addr()));
ldr(tmp, tmp);
sub(dst, src, tmp);
lsr(dst, dst, shift);
pop(regs, sp);
}
}
void MacroAssembler::encode_klass_not_null(Register dst, Register src) {
if (CompressedKlassPointers::base() != nullptr && AOTCodeCache::is_on_for_dump()) {
encode_klass_not_null_for_aot(dst, src);
return;
}
switch (klass_decode_mode()) {
switch (decode_mode) {
case KlassDecodeZero:
if (CompressedKlassPointers::shift() != 0) {
lsr(dst, src, CompressedKlassPointers::shift());
} else {
if (dst != src) mov(dst, src);
}
lsr(dst, src, shift);
break;
case KlassDecodeXor:
if (CompressedKlassPointers::shift() != 0) {
eor(dst, src, (uint64_t)CompressedKlassPointers::base());
lsr(dst, dst, CompressedKlassPointers::shift());
} else {
eor(dst, src, (uint64_t)CompressedKlassPointers::base());
}
eor(dst, src, (uint64_t)base);
lsr(dst, dst, shift);
break;
case KlassDecodeMovk:
if (CompressedKlassPointers::shift() != 0) {
ubfx(dst, src, CompressedKlassPointers::shift(), 32);
if (shift != 0) {
ubfx(dst, src, shift, 32);
} else {
movw(dst, src);
}
break;
case KlassDecodeFallback: {
mov(tmp, base);
sub(dst, src, tmp);
lsr(dst, dst, shift);
break;
}
case KlassDecodeNone:
ShouldNotReachHere();
break;
}
#ifdef ASSERT
if (tmp != dst) {
mov(tmp, 0xdead);
}
#endif // ASSERT
}
void MacroAssembler::encode_klass_not_null(Register r) {
encode_klass_not_null(r, r);
void MacroAssembler::decode_klass_not_null(Register dst, Register src, Register tmp) {
emit_decode_klass_not_null(dst, src, tmp,
CompressedKlassPointers::base(),
CompressedKlassPointers::shift(),
klass_decode_mode());
}
void MacroAssembler::decode_klass_not_null_for_aot(Register dst, Register src) {
// we have to load the klass base from the AOT constants area but
// not the shift because it is not allowed to change
int shift = CompressedKlassPointers::shift();
assert(shift >= 0 && shift <= CompressedKlassPointers::max_shift(), "unexpected compressed klass shift!");
if (dst != src) {
// we can load the base into dst then add the offset with a suitable shift
lea(dst, ExternalAddress(CompressedKlassPointers::base_addr()));
ldr(dst, dst);
add(dst, dst, src, LSL, shift);
} else {
// we need an extra register in order to load the coop base
Register tmp = pick_different_tmp(dst, src);
RegSet regs = RegSet::of(tmp);
push(regs, sp);
void MacroAssembler::emit_decode_klass_not_null(Register dst, Register src, Register tmp,
address base, int shift, KlassDecodeMode decode_mode) {
assert_different_registers(tmp, src);
assert(tmp != noreg, "valid tmp required");
if (AOTCodeCache::is_on_for_dump()) {
// We are generating code during AOT buildup that will run in *future* processes
// with likely different encoding settings. Therefore, we have to load the
// encoding base dynamically, we cannot just bake it in as immediate.
// Note that we only need to do this for base. The encoding shift would be the
// same between build time and runtime: the standard precomputed shift.
assert(shift == ArchiveBuilder::precomputed_narrow_klass_shift(), "unexpected compressed klass shift!");
lea(tmp, ExternalAddress(CompressedKlassPointers::base_addr()));
ldr(tmp, tmp);
add(dst, tmp, src, LSL, shift);
pop(regs, sp);
}
}
void MacroAssembler::decode_klass_not_null(Register dst, Register src) {
if (AOTCodeCache::is_on_for_dump()) {
decode_klass_not_null_for_aot(dst, src);
return;
}
switch (klass_decode_mode()) {
case KlassDecodeZero:
if (CompressedKlassPointers::shift() != 0) {
lsl(dst, src, CompressedKlassPointers::shift());
} else {
if (dst != src) mov(dst, src);
}
switch (decode_mode) {
case KlassDecodeZero: // 0-1 instructions
lsl(dst, src, shift);
break;
case KlassDecodeXor:
if (CompressedKlassPointers::shift() != 0) {
lsl(dst, src, CompressedKlassPointers::shift());
eor(dst, dst, (uint64_t)CompressedKlassPointers::base());
} else {
eor(dst, src, (uint64_t)CompressedKlassPointers::base());
}
case KlassDecodeXor: // 1-2 instructions
lsl(dst, src, shift);
eor(dst, dst, (uint64_t)base);
break;
case KlassDecodeMovk: {
case KlassDecodeMovk: { // 1-3 instructions
const uint64_t shifted_base =
(uint64_t)CompressedKlassPointers::base() >> CompressedKlassPointers::shift();
(uint64_t)base >> shift;
if (dst != src) movw(dst, src);
movk(dst, shifted_base >> 32, 32);
lsl(dst, dst, shift);
break;
}
if (CompressedKlassPointers::shift() != 0) {
lsl(dst, dst, CompressedKlassPointers::shift());
}
case KlassDecodeFallback: { // 3-4 instructions
mov(tmp, base);
add(dst, tmp, src, LSL, shift);
break;
}
@ -5500,10 +5505,14 @@ void MacroAssembler::decode_klass_not_null(Register dst, Register src) {
ShouldNotReachHere();
break;
}
}
void MacroAssembler::decode_klass_not_null(Register r) {
decode_klass_not_null(r, r);
#ifdef ASSERT
// Always clobber tmp
if (tmp != dst) {
mov(tmp, 0xdead);
}
#endif // ASSERT
}
void MacroAssembler::set_narrow_oop(Register dst, jobject obj) {
@ -7155,7 +7164,7 @@ void MacroAssembler::fast_lock(Register basic_lock, Register obj, Register t1, R
}
if (DiagnoseSyncOnValueBasedClasses != 0) {
load_klass(t1, obj);
load_klass(t1, obj, rscratch1);
ldrb(t1, Address(t1, Klass::misc_flags_offset()));
tst(t1, KlassFlags::_misc_is_value_based_class);
br(Assembler::NE, slow);
@ -7180,8 +7189,7 @@ void MacroAssembler::fast_lock(Register basic_lock, Register obj, Register t1, R
assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea");
orr(mark, mark, markWord::unlocked_value);
eor(t, mark, markWord::unlocked_value);
cmpxchg(/*addr*/ obj, /*expected*/ mark, /*new*/ t, Assembler::xword,
/*acquire*/ true, /*release*/ false, /*weak*/ false, noreg);
cmpxchg(/*addr*/ obj, /*expected*/ mark, /*new*/ t, Assembler::xword, memory_order_acquire);
br(Assembler::NE, slow);
bind(push);
@ -7249,8 +7257,7 @@ void MacroAssembler::fast_unlock(Register obj, Register t1, Register t2, Registe
// Try to unlock. Transition lock bits 0b00 => 0b01
assert(oopDesc::mark_offset_in_bytes() == 0, "required to avoid lea");
orr(t, mark, markWord::unlocked_value);
cmpxchg(obj, mark, t, Assembler::xword,
/*acquire*/ false, /*release*/ true, /*weak*/ false, noreg);
cmpxchg(obj, mark, t, Assembler::xword, memory_order_release);
br(Assembler::EQ, unlocked);
bind(push_and_slow);

View File

@ -32,11 +32,13 @@
#include "metaprogramming/enableIf.hpp"
#include "oops/compressedOops.hpp"
#include "oops/compressedKlass.hpp"
#include "runtime/atomicAccess.hpp"
#include "runtime/vm_version.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/powerOfTwo.hpp"
class OopMap;
struct GtestFriendToMacroAssembler;
// MacroAssembler extends Assembler by frequently used macros.
//
@ -45,6 +47,7 @@ class OopMap;
class MacroAssembler: public Assembler {
friend class LIR_Assembler;
friend struct GtestFriendToMacroAssembler;
public:
using Assembler::mov;
@ -90,28 +93,31 @@ class MacroAssembler: public Assembler {
void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions = true);
private:
enum KlassDecodeMode {
KlassDecodeNone,
KlassDecodeZero,
KlassDecodeXor,
KlassDecodeMovk
KlassDecodeMovk,
KlassDecodeFallback
};
// Calculate decoding mode based on given parameters, used for checking then ultimately setting.
static KlassDecodeMode klass_decode_mode(address base, int shift, const size_t range);
private:
static KlassDecodeMode _klass_decode_mode;
// Returns above setting with asserts
static KlassDecodeMode klass_decode_mode();
public:
// Checks the decode mode and returns false if not compatible with preferred decoding mode.
static bool check_klass_decode_mode(address base, int shift, const size_t range);
// Calculate decoding mode based on given parameters, used for checking then ultimately setting.
static KlassDecodeMode klass_decode_mode(address base, int shift, const size_t range);
// Sets the decode mode and returns false if cannot be set.
static bool set_klass_decode_mode(address base, int shift, const size_t range);
void emit_encode_klass_not_null(Register dst, Register src, Register tmp,
address base, int shift, KlassDecodeMode decode_mode);
void emit_decode_klass_not_null(Register dst, Register src, Register tmp,
address base, int shift, KlassDecodeMode decode_mode);
public:
// Determines the decode mode best suited for the given encoding parameters.
static void initialize_klass_decode_mode(address base, int shift, const size_t range);
public:
MacroAssembler(CodeBuffer* code) : Assembler(code) {}
@ -307,19 +313,27 @@ class MacroAssembler: public Assembler {
}
inline void lslw(Register Rd, Register Rn, unsigned imm) {
ubfmw(Rd, Rn, ((32 - imm) & 31), (31 - imm));
if (imm > 0 || Rd != Rn) {
ubfmw(Rd, Rn, ((32 - imm) & 31), (31 - imm));
}
}
inline void lsl(Register Rd, Register Rn, unsigned imm) {
ubfm(Rd, Rn, ((64 - imm) & 63), (63 - imm));
if (imm > 0 || Rd != Rn) {
ubfm(Rd, Rn, ((64 - imm) & 63), (63 - imm));
}
}
inline void lsrw(Register Rd, Register Rn, unsigned imm) {
ubfmw(Rd, Rn, imm, 31);
if (imm > 0 || Rd != Rn) {
ubfmw(Rd, Rn, imm, 31);
}
}
inline void lsr(Register Rd, Register Rn, unsigned imm) {
ubfm(Rd, Rn, imm, 63);
if (imm > 0 || Rd != Rn) {
ubfm(Rd, Rn, imm, 63);
}
}
inline void rorw(Register Rd, Register Rn, unsigned imm) {
@ -923,9 +937,10 @@ public:
// oop manipulations
void load_narrow_klass_compact(Register dst, Register src);
void load_klass(Register dst, Register src);
void store_klass(Register dst, Register src);
void cmp_klass(Register obj, Register klass, Register tmp);
void load_narrow_klass(Register dst, Register src);
void load_klass(Register dst, Register src, Register tmp);
void store_klass(Register dst, Register src, Register tmp);
void cmp_klass(Register obj, Register klass, Register tmp, Register tmp2);
void cmp_klasses_from_objects(Register obj1, Register obj2, Register tmp1, Register tmp2);
void resolve_weak_handle(Register result, Register tmp1, Register tmp2);
@ -970,12 +985,8 @@ public:
void set_narrow_oop(Register dst, jobject obj);
void decode_klass_not_null_for_aot(Register dst, Register src);
void encode_klass_not_null_for_aot(Register dst, Register src);
void encode_klass_not_null(Register r);
void decode_klass_not_null(Register r);
void encode_klass_not_null(Register dst, Register src);
void decode_klass_not_null(Register dst, Register src);
void encode_klass_not_null(Register dst, Register src, Register tmp);
void decode_klass_not_null(Register dst, Register src, Register tmp);
void set_narrow_klass(Register dst, Klass* k);
@ -1239,12 +1250,25 @@ public:
str(rscratch1, adr);
}
private:
// A generic CAS; success or failure is in the EQ flag.
// Clobbers rscratch1
void cmpxchg(Register addr, Register expected, Register new_val,
enum operand_size size,
bool acquire, bool release, bool weak,
Register result);
enum operand_size size, enum atomic_memory_order order,
bool weak, Register result);
public:
void cmpxchg(Register addr, Register expected, Register new_val,
enum operand_size size, enum atomic_memory_order order,
Register result = noreg) {
cmpxchg(addr, expected, new_val, size, order, /* weak */ false, result);
}
void cmpxchg_weak(Register addr, Register expected, Register new_val,
enum operand_size size, enum atomic_memory_order order,
Register result = noreg) {
cmpxchg(addr, expected, new_val, size, order, /* weak */ true, result);
}
#ifdef ASSERT
// Template short-hand support to clean-up after a failed call to trampoline
@ -1339,15 +1363,16 @@ public:
static bool far_branches() {
return ReservedCodeCacheSize > branch_range;
}
// Check if branches to the non nmethod section require a far jump
// Check if the static call stub branch needs a far jump.
static bool codestub_branch_needs_far_jump() {
if (AOTCodeCache::is_on_for_dump()) {
// To calculate far_codestub_branch_size correctly.
// To calculate static_call_stub_size correctly.
return true;
}
return CodeCache::max_distance_to_non_nmethod() > branch_range;
return far_branches();
}
// Check if a branch to the given address needs a far jump.
static bool target_needs_far_branch(address addr);
// Emit a direct call/jump if the entry address will always be in range,
// otherwise a far call/jump.
@ -1359,18 +1384,10 @@ public:
// In the case of a far call/jump, the entry address is put in the tmp register.
// The tmp register is invalidated.
//
// Far_jump returns the amount of the emitted code.
void far_call(Address entry, Register tmp = rscratch1);
// Far_jump returns the amount of the emitted code.
int far_jump(Address entry, Register tmp = rscratch1);
static int far_codestub_branch_size() {
if (codestub_branch_needs_far_jump()) {
return 3 * 4; // adrp, add, br
} else {
return 4;
}
}
// Emit the CompiledIC call idiom
address ic_call(address entry, jint method_index = 0);
static int ic_check_size();
@ -1843,13 +1860,19 @@ public:
#undef SVE_DESTRUCTIVE_TERNARY_INS
using Assembler::sve_eor3;
void sve_eor3(FloatRegister Zd, FloatRegister Zm, FloatRegister Zk) {
if (Zd != Zm && Zd != Zk) {
try_to_replace_prev_vector_copy_with_movprfx(Zd);
}
Assembler::sve_eor3(Zd, Zm, Zk);
#define SVE_DESTRUCTIVE_TERNARY_UNPRED_INS(NAME) \
using Assembler::NAME; \
void NAME(FloatRegister Zd, FloatRegister Zm, FloatRegister Zk) { \
if (Zd != Zm && Zd != Zk) { \
try_to_replace_prev_vector_copy_with_movprfx(Zd); \
} \
Assembler::NAME(Zd, Zm, Zk); \
}
SVE_DESTRUCTIVE_TERNARY_UNPRED_INS(sve_bsl);
SVE_DESTRUCTIVE_TERNARY_UNPRED_INS(sve_eor3);
#undef SVE_DESTRUCTIVE_TERNARY_UNPRED_INS
};
#ifdef ASSERT

View File

@ -76,7 +76,7 @@ void MethodHandles::verify_klass(MacroAssembler* _masm,
__ verify_oop(obj);
__ cbz(obj, L_bad);
__ push(RegSet::of(temp, temp2), sp);
__ load_klass(temp, obj);
__ load_klass(temp, obj, temp2);
__ cmpptr(temp, ExternalAddress((address) klass_addr));
__ br(Assembler::EQ, L_ok);
intptr_t super_check_offset = klass->super_check_offset();
@ -368,7 +368,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
__ null_check(receiver_reg);
} else {
// load receiver klass itself
__ load_klass(temp1_recv_klass, receiver_reg);
__ load_klass(temp1_recv_klass, receiver_reg, temp2);
__ verify_klass_ptr(temp1_recv_klass);
}
BLOCK_COMMENT("check_receiver {");
@ -376,7 +376,7 @@ void MethodHandles::generate_method_handle_dispatch(MacroAssembler* _masm,
// Check the receiver against the MemberName.clazz
if (VerifyMethodHandles && iid == vmIntrinsics::_linkToSpecial) {
// Did not load it above...
__ load_klass(temp1_recv_klass, receiver_reg);
__ load_klass(temp1_recv_klass, receiver_reg, temp2);
__ verify_klass_ptr(temp1_recv_klass);
}
if (VerifyMethodHandles && iid != vmIntrinsics::_linkToInterface) {

View File

@ -123,7 +123,7 @@ void NativeCall::insert(address code_pos, address entry) { Unimplemented(); }
void NativeMovConstReg::verify() {
if (! (nativeInstruction_at(instruction_address())->is_movz() ||
is_adrp_at(instruction_address()) ||
is_ldr_literal_at(instruction_address())) ) {
is_load_literal_at(instruction_address())) ) {
fatal("should be MOVZ or ADRP or LDR (literal)");
}
}
@ -270,17 +270,17 @@ bool NativeInstruction::is_safepoint_poll() {
// a safepoint_poll is implemented in two steps as either
//
// adrp(reg, polling_page);
// ldr(zr, [reg, #offset]);
// ldrw(zr, [reg, #offset]);
//
// or
//
// mov(reg, polling_page);
// ldr(zr, [reg, #offset]);
// ldrw(zr, [reg, #offset]);
//
// or
//
// ldr(reg, [rthread, #offset]);
// ldr(zr, [reg, #offset]);
// ldrw(zr, [reg, #offset]);
//
// however, we cannot rely on the polling page address load always
// directly preceding the read from the page. C1 does that but C2
@ -301,11 +301,21 @@ bool NativeInstruction::is_adrp_at(address instr) {
return (Instruction_aarch64::extract(insn, 31, 24) & 0b10011111) == 0b10010000;
}
bool NativeInstruction::is_ldr_literal_at(address instr) {
bool NativeInstruction::is_load_literal_at(address instr) {
unsigned insn = *(unsigned*)instr;
return (Instruction_aarch64::extract(insn, 29, 24) & 0b011011) == 0b00011000;
}
bool NativeInstruction::is_ldr_gpr_literal_at(address instr) {
unsigned insn = *(unsigned*)instr;
return Instruction_aarch64::extract(insn, 31, 24) == 0b01011000;
}
bool NativeInstruction::is_ldrw_gpr_literal_at(address instr) {
unsigned insn = *(unsigned*)instr;
return Instruction_aarch64::extract(insn, 31, 24) == 0b00011000;
}
bool NativeInstruction::is_ldrw_to_zr(address instr) {
unsigned insn = *(unsigned*)instr;
return (Instruction_aarch64::extract(insn, 31, 22) == 0b1011100101 &&

View File

@ -107,10 +107,22 @@ public:
static bool is_adrp_at(address instr);
static bool is_ldr_literal_at(address instr);
static bool is_load_literal_at(address instr);
bool is_ldr_literal() {
return is_ldr_literal_at(addr_at(0));
bool is_load_literal() {
return is_load_literal_at(addr_at(0));
}
static bool is_ldr_gpr_literal_at(address instr);
bool is_ldr_gpr_literal() {
return is_ldr_gpr_literal_at(addr_at(0));
}
static bool is_ldrw_gpr_literal_at(address instr);
bool is_ldrw_gpr_literal() {
return is_ldrw_gpr_literal_at(addr_at(0));
}
static bool is_ldrw_to_zr(address instr);
@ -125,7 +137,7 @@ public:
}
static bool maybe_cpool_ref(address instr) {
return is_adrp_at(instr) || is_ldr_literal_at(instr);
return is_adrp_at(instr) || is_load_literal_at(instr);
}
bool is_Membar() {
@ -267,7 +279,7 @@ public:
return addr_at(instruction_size);
else if (is_adrp_at(instruction_address()))
return addr_at(2*4);
else if (is_ldr_literal_at(instruction_address()))
else if (is_load_literal_at(instruction_address()))
return(addr_at(4));
assert(false, "Unknown instruction in NativeMovConstReg");
return nullptr;

View File

@ -28,6 +28,7 @@
#include "asm/register.hpp"
#include "utilities/checkedCast.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/powerOfTwo.hpp"
class VMRegImpl;
@ -513,28 +514,39 @@ template<int N> bool vs_write_before_read(const VSeq<N>& vout, const VSeq<N>& vi
template<int N>
VSeq<N/2> vs_front(const VSeq<N>& v) {
static_assert(N > 0 && ((N & 1) == 0), "sequence length must be even");
static_assert(N > 0 && is_even(N), "sequence length must be even");
return VSeq<N/2>(v.base(), v.delta());
}
template<int N>
VSeq<N/2> vs_back(const VSeq<N>& v) {
static_assert(N > 0 && ((N & 1) == 0), "sequence length must be even");
static_assert(N > 0 && is_even(N), "sequence length must be even");
return VSeq<N/2>(v.base() + N / 2 * v.delta(), v.delta());
}
template<int N>
VSeq<N/2> vs_even(const VSeq<N>& v) {
static_assert(N > 0 && ((N & 1) == 0), "sequence length must be even");
static_assert(N > 0 && is_even(N), "sequence length must be even");
return VSeq<N/2>(v.base(), v.delta() * 2);
}
template<int N>
VSeq<N/2> vs_odd(const VSeq<N>& v) {
static_assert(N > 0 && ((N & 1) == 0), "sequence length must be even");
static_assert(N > 0 && is_even(N), "sequence length must be even");
return VSeq<N/2>(v.base() + v.delta(), v.delta() * 2);
}
template<int N>
FloatRegister vs_head(const VSeq<N>& v) {
static_assert(N > 1, "sequence length must be greater than 1");
return v.base();
}
template<int N>
VSeq<N-1> vs_tail(const VSeq<N>& v) {
return VSeq<N-1>(v.base() + v.delta(), v.delta());
}
// convenience method to construct a vector register sequence that
// indexes its elements in reverse order to the original

View File

@ -41,7 +41,7 @@ void Relocation::pd_set_data_value(address x, bool verify_only) {
case relocInfo::oop_type:
{
oop_Relocation *reloc = (oop_Relocation *)this;
if (NativeInstruction::is_ldr_literal_at(addr())) {
if (NativeInstruction::is_load_literal_at(addr())) {
address constptr = (address)code()->oop_addr_at(reloc->oop_index());
bytes = MacroAssembler::pd_patch_instruction_size(addr(), constptr);
assert(*(address*)constptr == x, "error in oop relocation");

View File

@ -57,7 +57,7 @@
do_arch_entry, \
do_arch_entry_init, \
do_arch_entry_array) \
do_arch_blob(compiler, 70000) \
do_arch_blob(compiler, 75000) \
do_stub(compiler, vector_iota_indices) \
do_arch_entry_array(aarch64, compiler, vector_iota_indices, \
vector_iota_indices, vector_iota_indices, \

File diff suppressed because it is too large Load Diff

View File

@ -1123,9 +1123,9 @@ void TemplateTable::aastore() {
__ cbz(r0, is_null);
// Move subklass into r1
__ load_klass(r1, r0);
__ load_klass(r1, r0, rscratch1);
// Move superklass into r0
__ load_klass(r0, r3);
__ load_klass(r0, r3, rscratch1);
__ ldr(r0, Address(r0,
ObjArrayKlass::element_klass_offset()));
// Compress array + index*oopSize + 12 into a single register. Frees r2.
@ -1173,7 +1173,7 @@ void TemplateTable::bastore()
// Need to check whether array is boolean or byte
// since both types share the bastore bytecode.
__ load_klass(r2, r3);
__ load_klass(r2, r3, rscratch1);
__ ldrw(r2, Address(r2, Klass::layout_helper_offset()));
int diffbit_index = exact_log2(Klass::layout_helper_boolean_diffbit());
Label L_skip;
@ -2194,7 +2194,7 @@ void TemplateTable::_return(TosState state)
assert(state == vtos, "only valid state");
__ ldr(c_rarg1, aaddress(0));
__ load_klass(r3, c_rarg1);
__ load_klass(r3, c_rarg1, rscratch1);
__ ldrb(r3, Address(r3, Klass::misc_flags_offset()));
Label skip_register_finalizer;
__ tbz(r3, exact_log2(KlassFlags::_misc_has_finalizer), skip_register_finalizer);
@ -3338,8 +3338,8 @@ void TemplateTable::invokevirtual_helper(Register index,
Register recv,
Register flags)
{
// Uses temporary registers r0, r3
assert_different_registers(index, recv, r0, r3);
// Uses temporary registers r0, r3, rscratch1
assert_different_registers(index, recv, r0, r3, rscratch1);
// Test for an invoke of a final method
Label notFinal;
__ tbz(flags, ResolvedMethodEntry::is_vfinal_shift, notFinal);
@ -3363,7 +3363,7 @@ void TemplateTable::invokevirtual_helper(Register index,
__ bind(notFinal);
// get receiver klass
__ load_klass(r0, recv);
__ load_klass(r0, recv, rscratch1);
// profile this call
__ profile_virtual_call(r0, rlocals);
@ -3464,7 +3464,7 @@ void TemplateTable::invokeinterface(int byte_no) {
__ tbz(r3, ResolvedMethodEntry::is_vfinal_shift, notVFinal);
// Get receiver klass into r3
__ load_klass(r3, r2);
__ load_klass(r3, r2, rscratch1);
Label subtype;
__ check_klass_subtype(r3, r0, r4, subtype);
@ -3479,7 +3479,7 @@ void TemplateTable::invokeinterface(int byte_no) {
__ bind(notVFinal);
// Get receiver klass into r3
__ load_klass(r3, r2);
__ load_klass(r3, r2, rscratch1);
Label no_such_method;
@ -3678,7 +3678,7 @@ void TemplateTable::_new() {
__ mov(rscratch1, (intptr_t)markWord::prototype().value());
__ str(rscratch1, Address(r0, oopDesc::mark_offset_in_bytes()));
__ store_klass_gap(r0, zr); // zero klass gap for compressed oops
__ store_klass(r0, r4); // store klass last
__ store_klass(r0, r4, rscratch1); // store klass last
}
if (DTraceAllocProbes) {
@ -3759,7 +3759,7 @@ void TemplateTable::checkcast()
__ load_resolved_klass_at_offset(r2, r19, r0, rscratch1); // r0 = klass
__ bind(resolved);
__ load_klass(r19, r3);
__ load_klass(r19, r3, rscratch1);
// Generate subtype check. Blows r2, r5. Object in r3.
// Superklass in r0. Subklass in r19.
@ -3805,12 +3805,12 @@ void TemplateTable::instanceof() {
__ get_vm_result_metadata(r0, rthread);
__ pop(r3); // restore receiver
__ verify_oop(r3);
__ load_klass(r3, r3);
__ load_klass(r3, r3, rscratch1);
__ b(resolved);
// Get superklass in r0 and subklass in r3
__ bind(quicked);
__ load_klass(r3, r0);
__ load_klass(r3, r0, rscratch1);
__ load_resolved_klass_at_offset(r2, r19, r0, rscratch1);
__ bind(resolved);

View File

@ -454,6 +454,10 @@ void VM_Version::initialize() {
FLAG_SET_DEFAULT(UseChaCha20Intrinsics, false);
}
if (FLAG_IS_DEFAULT(UseIntPolyIntrinsics)) {
UseIntPolyIntrinsics = true;
}
if (supports_feature(CPU_ASIMD)) {
if (FLAG_IS_DEFAULT(UseKyberIntrinsics)) {
UseKyberIntrinsics = true;
@ -657,6 +661,10 @@ void VM_Version::initialize() {
FLAG_SET_DEFAULT(UsePoly1305Intrinsics, true);
}
if (FLAG_IS_DEFAULT(UseIntPoly25519Intrinsics)) {
FLAG_SET_DEFAULT(UseIntPoly25519Intrinsics, true);
}
if (FLAG_IS_DEFAULT(UseVectorizedHashCodeIntrinsic)) {
FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, true);
}

View File

@ -79,7 +79,7 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
// get receiver klass
address npe_addr = __ pc();
__ load_klass(r16, j_rarg0);
__ load_klass(r16, j_rarg0, rscratch1);
#ifndef PRODUCT
if (DebugVtables) {
@ -189,7 +189,7 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) {
// get receiver klass (also an implicit null-check)
address npe_addr = __ pc();
__ load_klass(recv_klass_reg, j_rarg0);
__ load_klass(recv_klass_reg, j_rarg0, rscratch1);
// Receiver subtype check against REFC.
// Get selected method from declaring class and itable index

View File

@ -1112,26 +1112,26 @@ uint Matcher::float_pressure_limit()
return (FLOATPRESSURE == -1) ? 30 : FLOATPRESSURE;
}
// Register for DIVI projection of divmodI
const RegMask& Matcher::divI_proj_mask() {
// Register for the first projection of an int pair
const RegMask& Matcher::firstI_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}
// Register for MODI projection of divmodI
const RegMask& Matcher::modI_proj_mask() {
// Register for the second projection of an int pair
const RegMask& Matcher::secondI_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}
// Register for DIVL projection of divmodL
const RegMask& Matcher::divL_proj_mask() {
// Register for the first projection of a long pair
const RegMask& Matcher::firstL_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}
// Register for MODL projection of divmodL
const RegMask& Matcher::modL_proj_mask() {
// Register for the second projection of a long pair
const RegMask& Matcher::secondL_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,7 +27,6 @@
public:
enum {
pc_return_offset = 0,
// All frames
link_offset = 0,
return_addr_offset = 1,
@ -61,6 +60,7 @@
// between a callee frame and its stack arguments, where it is part
// of the caller/callee overlap
metadata_words_at_top = 0,
// in bytes
frame_alignment = 16,
// size, in words, of maximum shift in frame position due to alignment
align_wiggle = 1
@ -122,6 +122,4 @@
// helper to update a map with callee-saved FP
static void update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr);
static jint interpreter_frame_expression_stack_direction() { return -1; }
#endif // CPU_ARM_FRAME_ARM_HPP

View File

@ -75,23 +75,46 @@ int Assembler::branch_destination(int inst, int pos) {
return r;
}
// Low-level andi-one-instruction-macro.
void Assembler::andi(Register a, Register s, const long ui16) {
if (is_power_of_2(((unsigned long) ui16)+1)) {
// Low-level andi-one-instruction-macro. May clobber CR0.
void Assembler::andi(Register a, Register s, julong int_or_long_const) {
// Instructions which don't set CR0 are preferred.
if (int_or_long_const == 0) {
// should not be handled as pow2minus1
li(a, 0);
} else if (is_power_of_2(int_or_long_const + 1)) {
// pow2minus1
clrldi(a, s, 64 - log2i_exact((((unsigned long) ui16)+1)));
} else if (is_power_of_2((jlong) ui16)) {
// pow2
rlwinm(a, s, 0, 31 - log2i_exact((jlong) ui16), 31 - log2i_exact((jlong) ui16));
} else if (is_power_of_2((jlong)-ui16)) {
// negpow2
clrrdi(a, s, log2i_exact((jlong)-ui16));
clrldi(a, s, 64 - log2i_exact(int_or_long_const + 1));
} else if (is_power_of_2(-int_or_long_const)) {
// negpow2 (includes (julong)min_jlong)
clrrdi(a, s, log2i_exact(-int_or_long_const));
} else if (is_uimm((jlong)int_or_long_const, 32) && has_consecutive_ones(int_or_long_const)) {
// consecutive ones
rlwinm(a, s, 0, count_leading_zeros((uint32_t)int_or_long_const),
31 - count_trailing_zeros((uint32_t)int_or_long_const));
} else if (is_uimm((jlong)int_or_long_const, 16)) {
// side effect: clobbers CR0
andi_(a, s, int_or_long_const);
} else {
assert(is_uimm(ui16, 16), "must be 16-bit unsigned immediate");
andi_(a, s, ui16);
assert(is_uimm((jlong)int_or_long_const, 32) && (int_or_long_const & 0xFFFF) == 0,
"not encodable: " UINT64_FORMAT_X, int_or_long_const);
// side effect: clobbers CR0
andis_(a, s, int_or_long_const >> 16);
}
}
// Check if int_or_long_const is supported by Assembler::andi.
bool Assembler::andi_supports(julong int_or_long_const) {
// 16 bit always possible by andi_ (but other instructions are preferred)
if (is_uimm((jlong)int_or_long_const, 16)) return true;
// special cases 32 bit: higher 16 bit and consecutive ones are supported
if (is_uimm((jlong)int_or_long_const, 32) &&
((int_or_long_const & 0xFFFF) == 0 || has_consecutive_ones(int_or_long_const))) return true;
// special cases 64 bit: clrldi, clrrdi
return is_power_of_2(int_or_long_const + 1) || is_power_of_2(-int_or_long_const);
}
// RegisterOrConstant version.
void Assembler::ld(Register d, RegisterOrConstant roc, Register s1) {
if (roc.is_constant()) {

View File

@ -1048,6 +1048,13 @@ class Assembler : public AbstractAssembler {
return (julong)x < maxplus1;
}
// Test if x has exactly one consecutive range of one bits (e.g. 00111000)
static bool has_consecutive_ones(julong x) {
if (x == max_julong) return true;
if (x == 0) return false;
return is_power_of_2((x >> count_trailing_zeros(x)) + 1);
}
protected:
// helpers
@ -1606,7 +1613,8 @@ class Assembler : public AbstractAssembler {
inline void isel_0( Register d, ConditionRegister cr, Condition cc, Register b = noreg);
// PPC 1, section 3.3.11, Fixed-Point Logical Instructions
void andi( Register a, Register s, long ui16); // optimized version
void andi( Register a, Register s, julong int_or_long_const); // optimized version, may clobber CR0
static bool andi_supports(julong int_or_long_const);
inline void andi_( Register a, Register s, int ui16);
inline void andis_( Register a, Register s, int ui16);
inline void ori( Register a, Register s, int ui16);

View File

@ -1669,26 +1669,40 @@ void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr
d = dest->as_register_lo();
l = left->as_register_lo();
}
long uimms = (unsigned long)uimm >> 16,
uimmss = (unsigned long)uimm >> 32;
long uimms = (unsigned long)uimm >> 16;
switch (code) {
case lir_logic_and:
if (uimmss != 0 || (uimms != 0 && (uimm & 0xFFFF) != 0) || is_power_of_2(uimm)) {
__ andi(d, l, uimm); // special cases
} else if (uimms != 0) { __ andis_(d, l, uimms); }
else { __ andi_(d, l, uimm); }
if (Assembler::andi_supports(uimm)) {
__ andi(d, l, uimm); // includes andis_ and special cases
} else { // for operands which are not generated by LIRGenerator::do_LogicOp
__ load_const_optimized(R0, uimm);
__ andr(d, l, R0);
}
break;
case lir_logic_or:
if (uimms != 0) { assert((uimm & 0xFFFF) == 0, "sanity"); __ oris(d, l, uimms); }
else { __ ori(d, l, uimm); }
if (Assembler::is_uimm(uimm, 16)) {
__ ori(d, l, uimm);
} else if ((uimm & 0xFFFF) == 0 && Assembler::is_uimm(uimms, 16)) {
__ oris(d, l, uimms);
} else { // for operands which are not generated by LIRGenerator::do_LogicOp
__ load_const_optimized(R0, uimm);
__ orr(d, l, R0);
}
break;
case lir_logic_xor:
if (uimm == -1) { __ nand(d, l, l); } // special case
else if (uimms != 0) { assert((uimm & 0xFFFF) == 0, "sanity"); __ xoris(d, l, uimms); }
else { __ xori(d, l, uimm); }
if (Assembler::is_uimm(uimm, 16)) {
__ xori(d, l, uimm);
} else if ((uimm & 0xFFFF) == 0 && Assembler::is_uimm(uimms, 16)) {
__ xoris(d, l, uimms);
} else if (uimm == -1) {
__ nand(d, l, l); // special case
} else { // for operands which are not generated by LIRGenerator::do_LogicOp
__ load_const_optimized(R0, uimm);
__ xorr(d, l, R0);
}
break;
default: ShouldNotReachHere();
@ -2717,7 +2731,13 @@ void LIR_Assembler::membar_storeload() {
}
void LIR_Assembler::on_spin_wait() {
Unimplemented();
// SMT priority hint: drop to low for the spin, then restore to medium so
// subsequent code is not penalised.
// Yield (or 27,27,27) is not used because it was never implemented on Power CPUs, see JDK-8201218.
__ block_comment("spin_wait {");
__ smt_prio_low();
__ smt_prio_medium();
__ block_comment("}");
}
void LIR_Assembler::leal(LIR_Opr addr_opr, LIR_Opr dest, LIR_PatchCode patch_code, CodeEmitInfo* info) {

View File

@ -578,18 +578,13 @@ inline bool can_handle_logic_op_as_uimm(ValueType *type, Bytecodes::Code bc) {
Assembler::is_uimm((jlong)((julong)int_or_long_const >> 16), 16)) return true;
// see Assembler::andi
if (bc == Bytecodes::_iand &&
(is_power_of_2(int_or_long_const+1) ||
is_power_of_2(int_or_long_const) ||
is_power_of_2(-int_or_long_const))) return true;
if (bc == Bytecodes::_land &&
(is_power_of_2((unsigned long)int_or_long_const+1) ||
(Assembler::is_uimm(int_or_long_const, 32) && is_power_of_2(int_or_long_const)) ||
(int_or_long_const != min_jlong && is_power_of_2(-int_or_long_const)))) return true;
if ((bc == Bytecodes::_iand || bc == Bytecodes::_land))
return Assembler::andi_supports(int_or_long_const);
// special case: xor -1
if ((bc == Bytecodes::_ixor || bc == Bytecodes::_lxor) &&
int_or_long_const == -1) return true;
if ((bc == Bytecodes::_ixor || bc == Bytecodes::_lxor))
return (int_or_long_const == -1);
return false;
}

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2025 SAP SE. All rights reserved.
* Copyright (c) 1999, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2026 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -760,22 +760,9 @@ OopMapSet* Runtime1::generate_code_for(StubId id, StubAssembler* sasm) {
break;
case StubId::c1_dtrace_object_alloc_id:
{ // O0: object
{
__ unimplemented("stub dtrace_object_alloc_id");
__ set_info("dtrace_object_alloc", dont_gc_arguments);
// // We can't gc here so skip the oopmap but make sure that all
// // the live registers get saved.
// save_live_registers(sasm);
//
// __ save_thread(L7_thread_cache);
// __ call(CAST_FROM_FN_PTR(address, static_cast<int (*)(oopDesc*)>(SharedRuntime::dtrace_object_alloc)),
// relocInfo::runtime_call_type);
// __ delayed()->mov(I0, O0);
// __ restore_thread(L7_thread_cache);
//
// restore_live_registers(sasm);
// __ ret();
// __ delayed()->restore();
}
break;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2025 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -391,8 +391,6 @@
}
enum {
// normal return address is 1 bundle past PC
pc_return_offset = 0,
// size, in words, of frame metadata (e.g. pc and link)
metadata_words = sizeof(java_abi) >> LogBytesPerWord,
// size, in words, of metadata at frame bottom, i.e. it is not part of the
@ -402,16 +400,13 @@
// between a callee frame and its stack arguments, where it is part
// of the caller/callee overlap
metadata_words_at_top = sizeof(java_abi) >> LogBytesPerWord,
// size, in words, of frame metadata at the frame top that needs
// to be reserved for callee functions in the runtime
// in bytes
frame_alignment = 16,
frame_alignment_in_words = frame_alignment >> LogBytesPerWord,
// size, in words, of maximum shift in frame position due to alignment
align_wiggle = 1
};
static jint interpreter_frame_expression_stack_direction() { return -1; }
// returns the sending frame, without applying any barriers
inline frame sender_raw(RegisterMap* map) const;

View File

@ -56,10 +56,11 @@
void ShenandoahBarrierSetAssembler::satb_barrier(MacroAssembler *masm,
Register base, RegisterOrConstant ind_or_offs,
Register tmp1, Register tmp2, Register tmp3,
MacroAssembler::PreservationLevel preservation_level) {
MacroAssembler::PreservationLevel preservation_level,
int extra_stack_space) {
if (ShenandoahSATBBarrier) {
__ block_comment("satb_barrier (shenandoahgc) {");
satb_barrier_impl(masm, 0, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level);
satb_barrier_impl(masm, 0, base, ind_or_offs, tmp1, tmp2, tmp3, preservation_level, extra_stack_space);
__ block_comment("} satb_barrier (shenandoahgc)");
}
}
@ -68,10 +69,11 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier(MacroAssembler *masm,
Register base, RegisterOrConstant ind_or_offs,
Register dst,
Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level) {
MacroAssembler::PreservationLevel preservation_level,
int extra_stack_space) {
if (ShenandoahLoadRefBarrier) {
__ block_comment("load_reference_barrier (shenandoahgc) {");
load_reference_barrier_impl(masm, decorators, base, ind_or_offs, dst, tmp1, tmp2, preservation_level);
load_reference_barrier_impl(masm, decorators, base, ind_or_offs, dst, tmp1, tmp2, preservation_level, extra_stack_space);
__ block_comment("} load_reference_barrier (shenandoahgc)");
}
}
@ -205,7 +207,8 @@ void ShenandoahBarrierSetAssembler::satb_barrier_impl(MacroAssembler *masm, Deco
Register base, RegisterOrConstant ind_or_offs,
Register pre_val,
Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level) {
MacroAssembler::PreservationLevel preservation_level,
int extra_stack_space) {
assert(ShenandoahSATBBarrier, "Should be checked by caller");
assert_different_registers(tmp1, tmp2, pre_val, noreg);
@ -299,7 +302,7 @@ void ShenandoahBarrierSetAssembler::satb_barrier_impl(MacroAssembler *masm, Deco
if (preserve_gp_registers) {
nbytes_save = (preserve_fp_registers
? MacroAssembler::num_volatile_gp_regs + MacroAssembler::num_volatile_fp_regs
: MacroAssembler::num_volatile_gp_regs) * BytesPerWord;
: MacroAssembler::num_volatile_gp_regs) * BytesPerWord + extra_stack_space;
__ save_volatile_gprs(R1_SP, -nbytes_save, preserve_fp_registers);
}
@ -343,7 +346,8 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier_impl(
Register base, RegisterOrConstant ind_or_offs,
Register dst,
Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level) {
MacroAssembler::PreservationLevel preservation_level,
int extra_stack_space) {
if (ind_or_offs.is_register()) {
assert_different_registers(tmp1, tmp2, base, ind_or_offs.as_register(), dst, noreg);
} else {
@ -430,7 +434,7 @@ void ShenandoahBarrierSetAssembler::load_reference_barrier_impl(
if (preserve_gp_registers) {
nbytes_save = (preserve_fp_registers
? MacroAssembler::num_volatile_gp_regs + MacroAssembler::num_volatile_fp_regs
: MacroAssembler::num_volatile_gp_regs) * BytesPerWord;
: MacroAssembler::num_volatile_gp_regs) * BytesPerWord + extra_stack_space;
__ save_volatile_gprs(R1_SP, -nbytes_save, preserve_fp_registers);
}
@ -655,6 +659,26 @@ void ShenandoahBarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembl
__ block_comment("} try_peek_weak_handle_in_nmethod (shenandoahgc)");
}
void ShenandoahBarrierSetAssembler::check_oop(MacroAssembler *masm, Register obj, const char* msg) {
if (!VerifyOops) {
return;
}
__ mr(R0, obj);
// This routine is sometimes called before applying GC barriers.
// With +COH, verification can touch the klass that may end up loading forwarding pointer instead.
Label L_skip;
if (UseCompactObjectHeaders) {
__ lbz(R0, in_bytes(ShenandoahThreadLocalData::gc_state_offset()), R16_thread);
__ andi_(R0, R0, ShenandoahHeap::HAS_FORWARDED);
__ bne(CR0, L_skip);
}
__ verify_oop(R0, msg);
__ bind(L_skip);
}
void ShenandoahBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
Register addr, Register count, Register preserve) {
assert(ShenandoahCardBarrier, "Should have been checked by caller");
@ -693,243 +717,119 @@ void ShenandoahBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssemb
#define __ ce->masm()->
void ShenandoahBarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler *ce, ShenandoahPreBarrierStub *stub) {
__ block_comment("gen_pre_barrier_stub (shenandoahgc) {");
ShenandoahBarrierSetC1 *bs = (ShenandoahBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1();
void ShenandoahBarrierSetAssembler::keepalive_barrier_c1_stub(LIR_Assembler* ce, ShenandoahKeepaliveBarrierStub* stub) {
__ block_comment("keepalive_barrier_stub (shenandoahgc) {");
__ bind(*stub->entry());
// GC status has already been verified by 'ShenandoahBarrierSetC1::pre_barrier'.
// This stub is the slowpath of that function.
ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1();
assert(stub->pre_val()->is_register(), "pre_val must be a register");
Register pre_val = stub->pre_val()->as_register();
Register obj = stub->obj()->as_register();
// If 'do_load()' returns false, the to-be-stored value is already available in 'stub->pre_val()'
// ("preloaded mode" of the store barrier).
// If 'do_load()' returns false, the to-be-stored value is already available in 'obj'
if (stub->do_load()) {
ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false);
ce->mem2reg(stub->addr(), stub->obj(), T_OBJECT, lir_patch_none, nullptr, false);
}
// Fast path: Reference is null.
__ cmpdi(CR0, pre_val, 0);
// Fast path: reference is null.
__ cmpdi(CR0, obj, 0);
__ bc_far_optimized(Assembler::bcondCRbiIs1_bhintNoHint, __ bi0(CR0, Assembler::equal), *stub->continuation());
// Argument passing via the stack.
__ std(pre_val, -8, R1_SP);
__ std(obj, -8, R1_SP);
__ load_const_optimized(R0, bs->pre_barrier_c1_runtime_code_blob()->code_begin());
address blob_addr = bs->keepalive_barrier_stub();
__ load_const_optimized(R0, blob_addr);
__ call_stub(R0);
__ b(*stub->continuation());
__ block_comment("} gen_pre_barrier_stub (shenandoahgc)");
__ block_comment("} keepalive_barrier_stub (shenandoahgc)");
}
void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assembler *ce,
ShenandoahLoadReferenceBarrierStub *stub) {
__ block_comment("gen_load_reference_barrier_stub (shenandoahgc) {");
void ShenandoahBarrierSetAssembler::load_reference_barrier_c1_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub) {
__ block_comment("load_reference_barrier_stub (shenandoahgc) {");
ShenandoahBarrierSetC1 *bs = (ShenandoahBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1();
__ bind(*stub->entry());
ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1();
Register obj = stub->obj()->as_register();
Register res = stub->result()->as_register();
Register addr = stub->addr()->as_pointer_register();
Register tmp1 = stub->tmp1()->as_register();
Register tmp2 = stub->tmp2()->as_register();
assert_different_registers(addr, res, tmp1, tmp2);
Register slow_result = stub->slow_result()->as_register();
assert_different_registers(obj, addr, slow_result);
assert(slow_result == R3_RET, "C1 must know about our slow call result register");
assert(R3_RET == res, "res must be r3");
// Argument passing via the stack.
__ std(obj, -8, R1_SP);
__ std(addr, -16, R1_SP);
if (res != obj) {
__ mr(res, obj);
address blob_addr = bs->load_reference_barrier_stub(stub->decorators());
__ load_const_optimized(R0, blob_addr);
__ call_stub(R0);
if (obj != slow_result) {
__ mr(obj, slow_result);
}
DecoratorSet decorators = stub->decorators();
/* ==== Check whether region is in collection set ==== */
// GC status (unstable) has already been verified by 'ShenandoahBarrierSetC1::load_reference_barrier_impl'.
// This stub is the slowpath of that function.
bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators);
bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators);
bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators);
bool is_native = ShenandoahBarrierSet::is_native_access(decorators);
if (is_strong) {
// Check whether object is in collection set.
__ load_const_optimized(tmp2, ShenandoahHeap::in_cset_fast_test_addr(), tmp1);
__ srdi(tmp1, obj, ShenandoahHeapRegion::region_size_bytes_shift_jint());
__ lbzx(tmp2, tmp1, tmp2);
__ andi_(tmp2, tmp2, 1);
__ bc_far_optimized(Assembler::bcondCRbiIs1_bhintNoHint, __ bi0(CR0, Assembler::equal), *stub->continuation());
}
address blob_addr = nullptr;
if (is_strong) {
if (is_native) {
blob_addr = bs->load_reference_barrier_strong_native_rt_code_blob()->code_begin();
} else {
blob_addr = bs->load_reference_barrier_strong_rt_code_blob()->code_begin();
}
} else if (is_weak) {
blob_addr = bs->load_reference_barrier_weak_rt_code_blob()->code_begin();
} else {
assert(is_phantom, "only remaining strength");
blob_addr = bs->load_reference_barrier_phantom_rt_code_blob()->code_begin();
}
assert(blob_addr != nullptr, "code blob cannot be found");
// Argument passing via the stack. 'obj' is passed implicitly (as asserted above).
__ std(addr, -8, R1_SP);
__ load_const_optimized(tmp1, blob_addr, tmp2);
__ call_stub(tmp1);
// 'res' is 'R3_RET'. The result is thus already in the correct register.
__ b(*stub->continuation());
__ block_comment("} gen_load_reference_barrier_stub (shenandoahgc)");
__ block_comment("} load_reference_barrier_stub (shenandoahgc)");
}
#undef __
#define __ sasm->
void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler *sasm) {
__ block_comment("generate_c1_pre_barrier_runtime_stub (shenandoahgc) {");
void ShenandoahBarrierSetAssembler::keepalive_barrier_c1_runtime_stub(StubAssembler* sasm) {
__ block_comment("keepalive_barrier_runtime_stub (shenandoahgc) {");
Label runtime, skip_barrier;
BarrierSet *bs = BarrierSet::barrier_set();
Register obj = R3_ARG1;
Register tmp1 = R11_scratch1;
Register tmp2 = R12_scratch2;
// Argument passing via the stack.
const int caller_stack_slots = 3;
// Save registers we are about to clobber
__ std(obj, -16, R1_SP);
__ std(tmp1, -24, R1_SP);
__ std(tmp2, -32, R1_SP);
Register R0_pre_val = R0;
__ ld(R0, -8, R1_SP);
Register R11_tmp1 = R11_scratch1;
__ std(R11_tmp1, -16, R1_SP);
Register R12_tmp2 = R12_scratch2;
__ std(R12_tmp2, -24, R1_SP);
// Pull the arguments from stack
__ ld(obj, -8, R1_SP);
/* ==== Check whether marking is active ==== */
// Even though gc status was checked in 'ShenandoahBarrierSetAssembler::gen_pre_barrier_stub',
// another check is required as a safepoint might have been reached in the meantime (JDK-8140588).
__ lbz(R12_tmp2, in_bytes(ShenandoahThreadLocalData::gc_state_offset()), R16_thread);
satb_barrier(sasm, noreg, noreg, obj, tmp1, tmp2, MacroAssembler::PRESERVATION_FRAME_LR_GP_FP_REGS, 4 * BytesPerWord);
__ andi_(R12_tmp2, R12_tmp2, ShenandoahHeap::MARKING);
__ beq(CR0, skip_barrier);
/* ==== Add previous value directly to thread-local SATB mark queue ==== */
// Check queue's capacity. Jump to runtime if no free slot is available.
__ ld(R12_tmp2, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset()), R16_thread);
__ cmpdi(CR0, R12_tmp2, 0);
__ beq(CR0, runtime);
// Capacity suffices. Decrement the queue's size by one slot (size of one oop).
__ addi(R12_tmp2, R12_tmp2, -wordSize);
__ std(R12_tmp2, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset()), R16_thread);
// Enqueue the previous value and skip the runtime invocation.
__ ld(R11_tmp1, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset()), R16_thread);
__ stdx(R0_pre_val, R11_tmp1, R12_tmp2);
__ b(skip_barrier);
__ bind(runtime);
/* ==== Invoke runtime to commit SATB mark queue to gc and allocate a new buffer ==== */
// Save to-be-preserved registers.
const int nbytes_save = (MacroAssembler::num_volatile_regs + caller_stack_slots) * BytesPerWord;
__ save_volatile_gprs(R1_SP, -nbytes_save);
__ save_LR(R11_tmp1);
__ push_frame_reg_args(nbytes_save, R11_tmp1);
// Invoke runtime.
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_pre), R0_pre_val);
// Restore to-be-preserved registers.
__ pop_frame();
__ restore_LR(R11_tmp1);
__ restore_volatile_gprs(R1_SP, -nbytes_save);
__ bind(skip_barrier);
// Restore spilled registers.
__ ld(R11_tmp1, -16, R1_SP);
__ ld(R12_tmp2, -24, R1_SP);
// Restore registers
__ ld(tmp2, -32, R1_SP);
__ ld(tmp1, -24, R1_SP);
__ ld(obj, -16, R1_SP);
__ blr();
__ block_comment("} generate_c1_pre_barrier_runtime_stub (shenandoahgc)");
__ block_comment("} keepalive_barrier_runtime_stub (shenandoahgc)");
}
void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler *sasm,
DecoratorSet decorators) {
__ block_comment("generate_c1_load_reference_barrier_runtime_stub (shenandoahgc) {");
void ShenandoahBarrierSetAssembler::load_reference_barrier_c1_runtime_stub(StubAssembler* sasm, DecoratorSet decorators) {
__ block_comment("load_reference_barrier_runtime_stub (shenandoahgc) {");
// Argument passing via the stack.
const int caller_stack_slots = 1;
Register obj = R3_ARG1;
Register addr = R4_ARG2;
Register tmp1 = R11_scratch1;
Register tmp2 = R12_scratch2;
// Save to-be-preserved registers.
const int nbytes_save = (MacroAssembler::num_volatile_regs - 1 // 'R3_ARG1' is skipped
+ caller_stack_slots) * BytesPerWord;
__ save_volatile_gprs(R1_SP, -nbytes_save, true, false);
// Save registers we are about to clobber
__ std(addr, -24, R1_SP);
__ std(tmp1, -32, R1_SP);
__ std(tmp2, -40, R1_SP);
// Load arguments from stack.
// No load required, as caller has already loaded obj into R3.
Register R3_obj = R3_ARG1;
Register R4_load_addr = R4_ARG2;
__ ld(R4_load_addr, -8, R1_SP);
// Pull the arguments from the stack
__ ld(obj, -8, R1_SP);
__ ld(addr, -16, R1_SP);
Register R11_tmp = R11_scratch1;
load_reference_barrier(sasm, decorators, addr, noreg, obj, tmp1, tmp2,
MacroAssembler::PRESERVATION_FRAME_LR_GP_FP_REGS, 5 * BytesPerWord);
/* ==== Invoke runtime ==== */
bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators);
bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators);
bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators);
bool is_native = ShenandoahBarrierSet::is_native_access(decorators);
address jrt_address = nullptr;
if (is_strong) {
if (is_native) {
jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong);
} else {
if (UseCompressedOops) {
jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong_narrow);
} else {
jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong);
}
}
} else if (is_weak) {
assert(!is_native, "weak load reference barrier must not be called off-heap");
if (UseCompressedOops) {
jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak_narrow);
} else {
jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak);
}
} else {
assert(is_phantom, "reference type must be phantom");
assert(is_native, "phantom load reference barrier must be called off-heap");
jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom);
}
assert(jrt_address != nullptr, "load reference barrier runtime routine cannot be found");
__ save_LR(R11_tmp);
__ push_frame_reg_args(nbytes_save, R11_tmp);
// Invoke runtime. Arguments are already stored in the corresponding registers.
__ call_VM_leaf(jrt_address, R3_obj, R4_load_addr);
// Restore to-be-preserved registers.
__ pop_frame();
__ restore_LR(R11_tmp);
__ restore_volatile_gprs(R1_SP, -nbytes_save, true, false); // Skip 'R3_RET' register.
// Restore registers
__ ld(tmp2, -40, R1_SP);
__ ld(tmp1, -32, R1_SP);
__ ld(addr, -24, R1_SP);
__ blr();
__ block_comment("} generate_c1_load_reference_barrier_runtime_stub (shenandoahgc)");
__ block_comment("} load_reference_barrier_runtime_stub (shenandoahgc)");
}
#undef __

View File

@ -34,7 +34,7 @@
#ifdef COMPILER1
class LIR_Assembler;
class ShenandoahPreBarrierStub;
class ShenandoahKeepaliveBarrierStub;
class ShenandoahLoadReferenceBarrierStub;
class StubAssembler;
@ -56,7 +56,8 @@ private:
Register base, RegisterOrConstant ind_or_offs,
Register pre_val,
Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level);
MacroAssembler::PreservationLevel preservation_level,
int extra_stack_space = 0);
void card_barrier(MacroAssembler* masm,
Register base, RegisterOrConstant ind_or_offs,
@ -66,7 +67,8 @@ private:
Register base, RegisterOrConstant ind_or_offs,
Register dst,
Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level);
MacroAssembler::PreservationLevel preservation_level,
int extra_stack_space = 0);
/* ==== Helper methods for barrier implementations ==== */
void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
@ -78,28 +80,26 @@ public:
/* ==== C1 stubs ==== */
#ifdef COMPILER1
void keepalive_barrier_c1_stub(LIR_Assembler* ce, ShenandoahKeepaliveBarrierStub* stub);
void keepalive_barrier_c1_runtime_stub(StubAssembler* sasm);
void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, DecoratorSet decorators);
void load_reference_barrier_c1_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
void load_reference_barrier_c1_runtime_stub(StubAssembler* sasm, DecoratorSet decorators);
#endif
/* ==== Available barriers (facades of the actual implementations) ==== */
void satb_barrier(MacroAssembler* masm,
Register base, RegisterOrConstant ind_or_offs,
Register tmp1, Register tmp2, Register tmp3,
MacroAssembler::PreservationLevel preservation_level);
MacroAssembler::PreservationLevel preservation_level,
int extra_stack_space = 0);
void load_reference_barrier(MacroAssembler* masm, DecoratorSet decorators,
Register base, RegisterOrConstant ind_or_offs,
Register dst,
Register tmp1, Register tmp2,
MacroAssembler::PreservationLevel preservation_level);
MacroAssembler::PreservationLevel preservation_level,
int extra_stack_space = 0);
/* ==== Access api ==== */
virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
@ -125,6 +125,8 @@ public:
virtual void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj,
Register tmp, Label& slow_path);
virtual void check_oop(MacroAssembler *masm, Register obj, const char* msg);
#ifdef COMPILER2
// Entry points from Matcher
void load_c2(const MachNode* node, MacroAssembler* masm, Register dst, Register addr, int disp, Register tmp1, Register tmp2, bool narrow, bool acquire);

View File

@ -4450,7 +4450,7 @@ void MacroAssembler::profile_receiver_type(Register recv, Register mdp, int mdp_
addi(offset, offset, receiver_step);
bdnz(L_loop_search_receiver);
// Fast: no receiver, but profile is full
// Fast: no receiver, but profile is not full
if (count != noreg) {
mtctr(count);
} else {

View File

@ -2138,6 +2138,9 @@ bool Matcher::match_rule_supported(int opcode) {
case Op_CacheWBPreSync:
case Op_CacheWBPostSync:
return VM_Version::supports_data_cache_line_flush();
case Op_OnSpinWait:
return VM_Version::supports_on_spin_wait();
}
return true; // Per default match rules are supported.
@ -2348,26 +2351,26 @@ uint Matcher::float_pressure_limit()
return (FLOATPRESSURE == -1) ? 28 : FLOATPRESSURE;
}
// Register for DIVI projection of divmodI.
const RegMask& Matcher::divI_proj_mask() {
// Register for the first projection of an int pair
const RegMask& Matcher::firstI_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}
// Register for MODI projection of divmodI.
const RegMask& Matcher::modI_proj_mask() {
// Register for the second projection of an int pair
const RegMask& Matcher::secondI_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}
// Register for DIVL projection of divmodL.
const RegMask& Matcher::divL_proj_mask() {
// Register for the first projection of a long pair
const RegMask& Matcher::firstL_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}
// Register for MODL projection of divmodL.
const RegMask& Matcher::modL_proj_mask() {
// Register for the second projection of a long pair
const RegMask& Matcher::secondL_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}
@ -3075,13 +3078,6 @@ encode %{
__ bind(done);
%}
enc_class enc_cmove_bso_reg(iRegLdst dst, flagsRegSrc crx, regD src) %{
Label done;
__ bso($crx$$CondRegister, done);
__ mffprd($dst$$Register, $src$$FloatRegister);
__ bind(done);
%}
enc_class enc_bc(flagsRegSrc crx, cmpOp cmp, Label lbl) %{
Label d; // dummy
__ bind(d);
@ -3553,9 +3549,6 @@ ins_attrib ins_alignment(1);
ins_attrib ins_cannot_rematerialize(false);
ins_attrib ins_should_rematerialize(false);
// Instruction has variable size depending on alignment.
ins_attrib ins_variable_size_depending_on_alignment(false);
// Instruction is a nop.
ins_attrib ins_is_nop(false);
@ -6931,6 +6924,21 @@ instruct membar_CPUOrder() %{
ins_pipe(pipe_class_default);
%}
instruct onspinwait() %{
match(OnSpinWait);
ins_cost(DEFAULT_COST);
format %{ "OnSpinWait (smt_prio_low ; smt_prio_medium)" %}
size(8);
ins_encode %{
__ block_comment("spin_wait {");
__ smt_prio_low();
__ smt_prio_medium();
__ block_comment("}");
%}
ins_pipe(pipe_class_default);
%}
//----------Conditional Move---------------------------------------------------
// Cmove using isel.
@ -6997,8 +7005,6 @@ instruct cmovF_reg(cmpOp cmp, flagsRegSrc crx, regF dst, regF src) %{
match(Set dst (CMoveF (Binary cmp crx) (Binary dst src)));
ins_cost(DEFAULT_COST+BRANCH_COST);
ins_variable_size_depending_on_alignment(true);
format %{ "CMOVEF $cmp, $crx, $dst, $src\n\t" %}
size(8);
ins_encode %{
@ -7016,8 +7022,6 @@ instruct cmovD_reg(cmpOp cmp, flagsRegSrc crx, regD dst, regD src) %{
match(Set dst (CMoveD (Binary cmp crx) (Binary dst src)));
ins_cost(DEFAULT_COST+BRANCH_COST);
ins_variable_size_depending_on_alignment(true);
format %{ "CMOVEF $cmp, $crx, $dst, $src\n\t" %}
size(8);
ins_encode %{
@ -8258,8 +8262,6 @@ instruct cmovI_bne_negI_reg(iRegIdst dst, flagsRegSrc crx, iRegIsrc src1) %{
effect(USE_DEF dst, USE src1, USE crx);
predicate(false);
ins_variable_size_depending_on_alignment(true);
format %{ "CMOVE $dst, neg($src1), $crx" %}
size(8);
ins_encode %{
@ -8316,8 +8318,6 @@ instruct cmovL_bne_negL_reg(iRegLdst dst, flagsRegSrc crx, iRegLsrc src1) %{
effect(USE_DEF dst, USE src1, USE crx);
predicate(false);
ins_variable_size_depending_on_alignment(true);
format %{ "CMOVE $dst, neg($src1), $crx" %}
size(8);
ins_encode %{
@ -9148,61 +9148,14 @@ instruct andI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
ins_pipe(pipe_class_default);
%}
// Left shifted Immediate And
instruct andI_reg_immIhi16(iRegIdst dst, iRegIsrc src1, immIhi16 src2, flagsRegCR0 cr0) %{
instruct andI_reg_immI(iRegIdst dst, iRegIsrc src1, immI src2, flagsRegCR0 cr0) %{
match(Set dst (AndI src1 src2));
predicate(Assembler::andi_supports((juint)(n->in(2)->get_int())));
effect(KILL cr0);
format %{ "ANDIS $dst, $src1, $src2.hi" %}
size(4);
ins_encode %{
__ andis_($dst$$Register, $src1$$Register, (int)((unsigned short)(($src2$$constant & 0xFFFF0000) >> 16)));
%}
ins_pipe(pipe_class_default);
%}
// Immediate And
instruct andI_reg_uimm16(iRegIdst dst, iRegIsrc src1, uimmI16 src2, flagsRegCR0 cr0) %{
match(Set dst (AndI src1 src2));
effect(KILL cr0);
format %{ "ANDI $dst, $src1, $src2" %}
size(4);
ins_encode %{
// FIXME: avoid andi_ ?
__ andi_($dst$$Register, $src1$$Register, $src2$$constant);
%}
ins_pipe(pipe_class_default);
%}
// Immediate And where the immediate is a negative power of 2.
instruct andI_reg_immInegpow2(iRegIdst dst, iRegIsrc src1, immInegpow2 src2) %{
match(Set dst (AndI src1 src2));
format %{ "ANDWI $dst, $src1, $src2" %}
size(4);
ins_encode %{
__ clrrdi($dst$$Register, $src1$$Register, log2i_exact(-(juint)$src2$$constant));
%}
ins_pipe(pipe_class_default);
%}
instruct andI_reg_immIpow2minus1(iRegIdst dst, iRegIsrc src1, immIpow2minus1 src2) %{
match(Set dst (AndI src1 src2));
format %{ "ANDWI $dst, $src1, $src2" %}
size(4);
ins_encode %{
__ clrldi($dst$$Register, $src1$$Register, 64 - log2i_exact((juint)$src2$$constant + 1u));
%}
ins_pipe(pipe_class_default);
%}
instruct andI_reg_immIpowerOf2(iRegIdst dst, iRegIsrc src1, immIpowerOf2 src2) %{
match(Set dst (AndI src1 src2));
predicate(UseRotateAndMaskInstructionsPPC64);
format %{ "ANDWI $dst, $src1, $src2" %}
size(4);
ins_encode %{
int bitpos = 31 - log2i_exact((juint)$src2$$constant);
__ rlwinm($dst$$Register, $src1$$Register, 0, bitpos, bitpos);
__ andi($dst$$Register, $src1$$Register, (juint)$src2$$constant); // optimized version
%}
ins_pipe(pipe_class_default);
%}
@ -9220,50 +9173,27 @@ instruct andL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
ins_pipe(pipe_class_default);
%}
// Immediate And long
instruct andL_reg_uimm16(iRegLdst dst, iRegLsrc src1, uimmL16 src2, flagsRegCR0 cr0) %{
instruct andL_reg_immL(iRegLdst dst, iRegLsrc src1, immL src2, flagsRegCR0 cr0) %{
match(Set dst (AndL src1 src2));
predicate(Assembler::andi_supports(n->in(2)->get_long()));
effect(KILL cr0);
format %{ "ANDI $dst, $src1, $src2 \t// long" %}
size(4);
ins_encode %{
// FIXME: avoid andi_ ?
__ andi_($dst$$Register, $src1$$Register, $src2$$constant);
%}
ins_pipe(pipe_class_default);
%}
// Immediate And Long where the immediate is a negative power of 2.
instruct andL_reg_immLnegpow2(iRegLdst dst, iRegLsrc src1, immLnegpow2 src2) %{
match(Set dst (AndL src1 src2));
format %{ "ANDDI $dst, $src1, $src2" %}
size(4);
ins_encode %{
__ clrrdi($dst$$Register, $src1$$Register, log2i_exact(-(julong)$src2$$constant));
%}
ins_pipe(pipe_class_default);
%}
instruct andL_reg_immLpow2minus1(iRegLdst dst, iRegLsrc src1, immLpow2minus1 src2) %{
match(Set dst (AndL src1 src2));
format %{ "ANDDI $dst, $src1, $src2" %}
size(4);
ins_encode %{
__ clrldi($dst$$Register, $src1$$Register, 64 - log2i_exact((julong)$src2$$constant + 1ull));
__ andi($dst$$Register, $src1$$Register, $src2$$constant); // optimized version
%}
ins_pipe(pipe_class_default);
%}
// AndL + ConvL2I.
instruct convL2I_andL_reg_immLpow2minus1(iRegIdst dst, iRegLsrc src1, immLpow2minus1 src2) %{
instruct convL2I_andL_reg_immL(iRegIdst dst, iRegLsrc src1, immL src2, flagsRegCR0 cr0) %{
match(Set dst (ConvL2I (AndL src1 src2)));
ins_cost(DEFAULT_COST);
format %{ "ANDDI $dst, $src1, $src2 \t// long + l2i" %}
predicate(Assembler::andi_supports(n->in(1)->in(2)->get_long()));
effect(KILL cr0);
format %{ "ANDI $dst, $src1, $src2 \t// long + l2i" %}
size(4);
ins_encode %{
__ clrldi($dst$$Register, $src1$$Register, 64 - log2i_exact((julong)$src2$$constant + 1ull));
__ andi($dst$$Register, $src1$$Register, $src2$$constant); // optimized version
%}
ins_pipe(pipe_class_default);
%}
@ -9276,7 +9206,7 @@ instruct orI_reg_reg(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
format %{ "OR $dst, $src1, $src2" %}
size(4);
ins_encode %{
__ or_unchecked($dst$$Register, $src1$$Register, $src2$$Register);
__ orr($dst$$Register, $src1$$Register, $src2$$Register);
%}
ins_pipe(pipe_class_default);
%}
@ -9288,7 +9218,7 @@ instruct orI_reg_reg_2(iRegIdst dst, iRegIsrc src1, iRegIsrc src2) %{
format %{ "OR $dst, $src1, $src2" %}
size(4);
ins_encode %{
__ or_unchecked($dst$$Register, $src1$$Register, $src2$$Register);
__ orr($dst$$Register, $src1$$Register, $src2$$Register);
%}
ins_pipe(pipe_class_default);
%}
@ -9326,7 +9256,7 @@ instruct orL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{
size(4);
format %{ "OR $dst, $src1, $src2 \t// long" %}
ins_encode %{
__ or_unchecked($dst$$Register, $src1$$Register, $src2$$Register);
__ orr($dst$$Register, $src1$$Register, $src2$$Register);
%}
ins_pipe(pipe_class_default);
%}
@ -9339,7 +9269,7 @@ instruct orI_regL_regL(iRegIdst dst, iRegLsrc src1, iRegLsrc src2) %{
format %{ "OR $dst, $src1, $src2 \t// long + l2i" %}
size(4);
ins_encode %{
__ or_unchecked($dst$$Register, $src1$$Register, $src2$$Register);
__ orr($dst$$Register, $src1$$Register, $src2$$Register);
%}
ins_pipe(pipe_class_default);
%}
@ -10008,6 +9938,34 @@ instruct convL2I_reg(iRegIdst dst, iRegLsrc src) %{
ins_pipe(pipe_class_default);
%}
instruct cmovI_bso_stackSlotL(iRegIdst dst, flagsRegSrc crx, stackSlotL src) %{
// no match-rule, false predicate
effect(DEF dst, USE crx, USE src);
predicate(false);
format %{ "CMOVI $crx, $dst, $src" %}
size(8);
ins_encode( enc_cmove_bso_stackSlotL(dst, crx, src) );
ins_pipe(pipe_class_default);
%}
instruct cmovI_bso_reg_con0(iRegIdst dst, flagsRegSrc crx, regD src) %{
// no match-rule, false predicate
effect(DEF dst, USE crx, USE src);
predicate(false);
format %{ "CMOVI $dst, $crx, $src, 0 \t// set to 0 if unordered" %}
size(12);
ins_encode %{
Label done;
__ li($dst$$Register, 0);
__ bso($crx$$CondRegister, done);
__ mffprd($dst$$Register, $src$$FloatRegister);
__ bind(done);
%}
ins_pipe(pipe_class_default);
%}
instruct convD2IRaw_regD(regD dst, regD src) %{
// no match-rule, false predicate
effect(DEF dst, USE src);
@ -10021,88 +9979,6 @@ instruct convD2IRaw_regD(regD dst, regD src) %{
ins_pipe(pipe_class_default);
%}
instruct cmovI_bso_stackSlotL(iRegIdst dst, flagsRegSrc crx, stackSlotL src) %{
// no match-rule, false predicate
effect(DEF dst, USE crx, USE src);
predicate(false);
ins_variable_size_depending_on_alignment(true);
format %{ "CMOVI $crx, $dst, $src" %}
size(8);
ins_encode( enc_cmove_bso_stackSlotL(dst, crx, src) );
ins_pipe(pipe_class_default);
%}
instruct cmovI_bso_reg(iRegIdst dst, flagsRegSrc crx, regD src) %{
// no match-rule, false predicate
effect(DEF dst, USE crx, USE src);
predicate(false);
ins_variable_size_depending_on_alignment(true);
format %{ "CMOVI $crx, $dst, $src" %}
size(8);
ins_encode( enc_cmove_bso_reg(dst, crx, src) );
ins_pipe(pipe_class_default);
%}
instruct cmovI_bso_reg_conLvalue0_Ex(iRegIdst dst, flagsRegSrc crx, regD src) %{
// no match-rule, false predicate
effect(DEF dst, USE crx, USE src);
predicate(false);
format %{ "CMOVI $dst, $crx, $src \t// postalloc expanded" %}
postalloc_expand %{
//
// replaces
//
// region dst crx src
// \ | | /
// dst=cmovI_bso_reg_conLvalue0
//
// with
//
// region dst
// \ /
// dst=loadConI16(0)
// |
// ^ region dst crx src
// | \ | | /
// dst=cmovI_bso_reg
//
// Create new nodes.
MachNode *m1 = new loadConI16Node();
MachNode *m2 = new cmovI_bso_regNode();
// inputs for new nodes
m1->add_req(n_region);
m2->add_req(n_region, n_crx, n_src);
// precedences for new nodes
m2->add_prec(m1);
// operands for new nodes
m1->_opnds[0] = op_dst;
m1->_opnds[1] = new immI16Oper(0);
m2->_opnds[0] = op_dst;
m2->_opnds[1] = op_crx;
m2->_opnds[2] = op_src;
// registers for new nodes
ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst
ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst
// Insert new nodes.
nodes->push(m1);
nodes->push(m2);
%}
%}
// Double to Int conversion, NaN is mapped to 0. Special version for Power8.
instruct convD2I_reg_mffprd_ExEx(iRegIdst dst, regD src) %{
match(Set dst (ConvD2I src));
@ -10113,7 +9989,7 @@ instruct convD2I_reg_mffprd_ExEx(iRegIdst dst, regD src) %{
flagsReg crx;
cmpDUnordered_reg_reg(crx, src, src); // Check whether src is NaN.
convD2IRaw_regD(tmpD, src); // Convert float to int (speculated).
cmovI_bso_reg_conLvalue0_Ex(dst, crx, tmpD); // Cmove based on NaN check.
cmovI_bso_reg_con0(dst, crx, tmpD); // Cmove based on NaN check.
%}
%}
@ -10141,7 +10017,7 @@ instruct convF2I_regF_mffprd_ExEx(iRegIdst dst, regF src) %{
flagsReg crx;
cmpFUnordered_reg_reg(crx, src, src); // Check whether src is NaN.
convF2IRaw_regF(tmpF, src); // Convert float to int (speculated).
cmovI_bso_reg_conLvalue0_Ex(dst, crx, tmpF); // Cmove based on NaN check.
cmovI_bso_reg_con0(dst, crx, tmpF); // Cmove based on NaN check.
%}
%}
@ -10183,6 +10059,34 @@ instruct zeroExtendL_regL(iRegLdst dst, iRegLsrc src, immL_32bits mask) %{
ins_pipe(pipe_class_default);
%}
instruct cmovL_bso_stackSlotL(iRegLdst dst, flagsRegSrc crx, stackSlotL src) %{
// no match-rule, false predicate
effect(DEF dst, USE crx, USE src);
predicate(false);
format %{ "CMOVL $crx, $dst, $src" %}
size(8);
ins_encode( enc_cmove_bso_stackSlotL(dst, crx, src) );
ins_pipe(pipe_class_default);
%}
instruct cmovL_bso_reg_con0(iRegLdst dst, flagsRegSrc crx, regD src) %{
// no match-rule, false predicate
effect(DEF dst, USE crx, USE src);
predicate(false);
format %{ "CMOVL $dst, $crx, $src, 0 \t// set to 0 if unordered" %}
size(12);
ins_encode %{
Label done;
__ li($dst$$Register, 0);
__ bso($crx$$CondRegister, done);
__ mffprd($dst$$Register, $src$$FloatRegister);
__ bind(done);
%}
ins_pipe(pipe_class_default);
%}
instruct convF2LRaw_regF(regF dst, regF src) %{
// no match-rule, false predicate
effect(DEF dst, USE src);
@ -10196,85 +10100,6 @@ instruct convF2LRaw_regF(regF dst, regF src) %{
ins_pipe(pipe_class_default);
%}
instruct cmovL_bso_stackSlotL(iRegLdst dst, flagsRegSrc crx, stackSlotL src) %{
// no match-rule, false predicate
effect(DEF dst, USE crx, USE src);
predicate(false);
ins_variable_size_depending_on_alignment(true);
format %{ "CMOVL $crx, $dst, $src" %}
size(8);
ins_encode( enc_cmove_bso_stackSlotL(dst, crx, src) );
ins_pipe(pipe_class_default);
%}
instruct cmovL_bso_reg(iRegLdst dst, flagsRegSrc crx, regD src) %{
// no match-rule, false predicate
effect(DEF dst, USE crx, USE src);
predicate(false);
ins_variable_size_depending_on_alignment(true);
format %{ "CMOVL $crx, $dst, $src" %}
size(8);
ins_encode( enc_cmove_bso_reg(dst, crx, src) );
ins_pipe(pipe_class_default);
%}
instruct cmovL_bso_reg_conLvalue0_Ex(iRegLdst dst, flagsRegSrc crx, regD src) %{
// no match-rule, false predicate
effect(DEF dst, USE crx, USE src);
predicate(false);
format %{ "CMOVL $dst, $crx, $src \t// postalloc expanded" %}
postalloc_expand %{
//
// replaces
//
// region dst crx src
// \ | | /
// dst=cmovL_bso_reg_conLvalue0
//
// with
//
// region dst
// \ /
// dst=loadConL16(0)
// |
// ^ region dst crx src
// | \ | | /
// dst=cmovL_bso_reg
//
// Create new nodes.
MachNode *m1 = new loadConL16Node();
MachNode *m2 = new cmovL_bso_regNode();
// inputs for new nodes
m1->add_req(n_region);
m2->add_req(n_region, n_crx, n_src);
m2->add_prec(m1);
// operands for new nodes
m1->_opnds[0] = op_dst;
m1->_opnds[1] = new immL16Oper(0);
m2->_opnds[0] = op_dst;
m2->_opnds[1] = op_crx;
m2->_opnds[2] = op_src;
// registers for new nodes
ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst
ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // dst
// Insert new nodes.
nodes->push(m1);
nodes->push(m2);
%}
%}
// Float to Long conversion, NaN is mapped to 0. Special version for Power8.
instruct convF2L_reg_mffprd_ExEx(iRegLdst dst, regF src) %{
match(Set dst (ConvF2L src));
@ -10285,7 +10110,7 @@ instruct convF2L_reg_mffprd_ExEx(iRegLdst dst, regF src) %{
flagsReg crx;
cmpFUnordered_reg_reg(crx, src, src); // Check whether src is NaN.
convF2LRaw_regF(tmpF, src); // Convert float to long (speculated).
cmovL_bso_reg_conLvalue0_Ex(dst, crx, tmpF); // Cmove based on NaN check.
cmovL_bso_reg_con0(dst, crx, tmpF); // Cmove based on NaN check.
%}
%}
@ -10302,7 +10127,6 @@ instruct convD2LRaw_regD(regD dst, regD src) %{
ins_pipe(pipe_class_default);
%}
// Double to Long conversion, NaN is mapped to 0. Special version for Power8.
instruct convD2L_reg_mffprd_ExEx(iRegLdst dst, regD src) %{
match(Set dst (ConvD2L src));
@ -10313,7 +10137,7 @@ instruct convD2L_reg_mffprd_ExEx(iRegLdst dst, regD src) %{
flagsReg crx;
cmpDUnordered_reg_reg(crx, src, src); // Check whether src is NaN.
convD2LRaw_regD(tmpD, src); // Convert float to long (speculated).
cmovL_bso_reg_conLvalue0_Ex(dst, crx, tmpD); // Cmove based on NaN check.
cmovL_bso_reg_con0(dst, crx, tmpD); // Cmove based on NaN check.
%}
%}
@ -10835,84 +10659,22 @@ instruct cmpFUnordered_reg_reg(flagsReg crx, regF src1, regF src2) %{
ins_pipe(pipe_class_default);
%}
instruct cmov_bns_less(flagsReg crx) %{
// no match-rule, false predicate
effect(DEF crx);
predicate(false);
ins_variable_size_depending_on_alignment(true);
format %{ "CMOV $crx" %}
size(12);
ins_encode %{
Label done;
__ bns($crx$$CondRegister, done); // not unordered -> keep crx
__ li(R0, 0);
__ cmpwi($crx$$CondRegister, R0, 1); // unordered -> set crx to 'less'
__ bind(done);
%}
ins_pipe(pipe_class_default);
%}
// Compare floating, generate condition code.
instruct cmpF_reg_reg_Ex(flagsReg crx, regF src1, regF src2) %{
// FIXME: should we match 'If cmp (CmpF src1 src2))' ??
//
// The following code sequence occurs a lot in mpegaudio:
//
// block BXX:
// 0: instruct cmpFUnordered_reg_reg (cmpF_reg_reg-0):
// cmpFUrd CR6, F11, F9
// 4: instruct cmov_bns_less (cmpF_reg_reg-1):
// cmov CR6
// 8: instruct branchConSched:
// B_FARle CR6, B56 P=0.500000 C=-1.000000
instruct cmpF_reg_reg(flagsReg crx, regF src1, regF src2) %{
match(Set crx (CmpF src1 src2));
ins_cost(DEFAULT_COST+BRANCH_COST);
format %{ "CMPF $crx, $src1, $src2 \t// postalloc expanded" %}
postalloc_expand %{
//
// replaces
//
// region src1 src2
// \ | |
// crx=cmpF_reg_reg
//
// with
//
// region src1 src2
// \ | |
// crx=cmpFUnordered_reg_reg
// |
// ^ region
// | \
// crx=cmov_bns_less
//
// Create new nodes.
MachNode *m1 = new cmpFUnordered_reg_regNode();
MachNode *m2 = new cmov_bns_lessNode();
// inputs for new nodes
m1->add_req(n_region, n_src1, n_src2);
m2->add_req(n_region);
m2->add_prec(m1);
// operands for new nodes
m1->_opnds[0] = op_crx;
m1->_opnds[1] = op_src1;
m1->_opnds[2] = op_src2;
m2->_opnds[0] = op_crx;
// registers for new nodes
ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // crx
ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // crx
// Insert new nodes.
nodes->push(m1);
nodes->push(m2);
format %{ "CMPF $crx, $src1, $src2" %}
size(16);
ins_encode %{
Label done;
__ fcmpu($crx$$CondRegister, $src1$$FloatRegister, $src2$$FloatRegister);
__ bns($crx$$CondRegister, done);
__ li(R0, 0);
__ cmpwi($crx$$CondRegister, R0, 1);
__ bind(done);
%}
ins_pipe(pipe_class_default);
%}
// Compare float, generate -1,0,1
@ -10950,53 +10712,21 @@ instruct cmpDUnordered_reg_reg(flagsReg crx, regD src1, regD src2) %{
ins_pipe(pipe_class_default);
%}
instruct cmpD_reg_reg_Ex(flagsReg crx, regD src1, regD src2) %{
instruct cmpD_reg_reg(flagsReg crx, regD src1, regD src2) %{
match(Set crx (CmpD src1 src2));
ins_cost(DEFAULT_COST+BRANCH_COST);
format %{ "CmpD $crx, $src1, $src2 \t// postalloc expanded" %}
postalloc_expand %{
//
// replaces
//
// region src1 src2
// \ | |
// crx=cmpD_reg_reg
//
// with
//
// region src1 src2
// \ | |
// crx=cmpDUnordered_reg_reg
// |
// ^ region
// | \
// crx=cmov_bns_less
//
// create new nodes
MachNode *m1 = new cmpDUnordered_reg_regNode();
MachNode *m2 = new cmov_bns_lessNode();
// inputs for new nodes
m1->add_req(n_region, n_src1, n_src2);
m2->add_req(n_region);
m2->add_prec(m1);
// operands for new nodes
m1->_opnds[0] = op_crx;
m1->_opnds[1] = op_src1;
m1->_opnds[2] = op_src2;
m2->_opnds[0] = op_crx;
// registers for new nodes
ra_->set_pair(m1->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // crx
ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); // crx
// Insert new nodes.
nodes->push(m1);
nodes->push(m2);
format %{ "CMPD $crx, $src1, $src2" %}
size(16);
ins_encode %{
Label done;
__ fcmpu($crx$$CondRegister, $src1$$FloatRegister, $src2$$FloatRegister);
__ bns($crx$$CondRegister, done);
__ li(R0, 0);
__ cmpwi($crx$$CondRegister, R0, 1);
__ bind(done);
%}
ins_pipe(pipe_class_default);
%}
// Compare double, generate -1,0,1

View File

@ -2320,10 +2320,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// Make sure that thread is non-volatile; it crosses a bunch of VM calls below.
assert(R16_thread->is_nonvolatile(), "thread must be in non-volatile register");
# if 0
// DTrace method entry
# endif
// Lock a synchronized method.
// --------------------------------------------------------------------------
@ -2595,10 +2591,6 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
__ bind(done);
}
# if 0
// DTrace method exit
# endif
// Clear "last Java frame" SP and PC.
// --------------------------------------------------------------------------

View File

@ -67,6 +67,8 @@ public:
static bool supports_float16() { return PowerArchitecturePPC64 >= 9; }
static bool supports_on_spin_wait() { return true; }
static bool is_determine_features_test_running() { return _is_determine_features_test_running; }
// CPU instruction support
static bool has_mfdscr() { return (_features & mfdscr_m) != 0; } // Power8, but may be unavailable (QEMU)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -103,8 +103,6 @@
public:
enum {
pc_return_offset = 0,
// All frames
link_offset = -2,
return_addr_offset = -1,
@ -220,8 +218,6 @@
// deoptimization support
void interpreter_frame_set_last_sp(intptr_t* last_sp);
static jint interpreter_frame_expression_stack_direction() { return -1; }
// returns the sending frame, without applying any barriers
inline frame sender_raw(RegisterMap* map) const;

View File

@ -352,8 +352,8 @@ void BarrierSetAssembler::check_oop(MacroAssembler* masm, Register obj, Register
__ bne(tmp1, tmp2, error);
// Make sure klass is 'reasonable', which is not zero.
__ load_klass(obj, obj, tmp1); // get klass
__ beqz(obj, error); // if klass is null it is broken
__ load_narrow_klass(tmp1, obj); // get klass
__ beqz(tmp1, error); // if klass is null it is broken
}
void BarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj,

View File

@ -433,6 +433,32 @@ void ShenandoahBarrierSetAssembler::try_peek_weak_handle_in_nmethod(MacroAssembl
__ bind(done);
}
void ShenandoahBarrierSetAssembler::check_oop(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2, Label& L_error) {
// Check if the oop is in the right area of memory
__ mv(tmp2, (intptr_t) Universe::verify_oop_mask());
__ andr(tmp1, obj, tmp2);
__ mv(tmp2, (intptr_t) Universe::verify_oop_bits());
// Compare tmp1 and tmp2.
__ bne(tmp1, tmp2, L_error);
// This routine is sometimes called before applying GC barriers.
// With +COH, loading the klass may end up loading forwarding pointer instead.
Label L_skip;
if (UseCompactObjectHeaders) {
Address gc_state(xthread, ShenandoahThreadLocalData::gc_state_offset());
__ lbu(tmp1, gc_state);
__ test_bit(tmp1, tmp1, ShenandoahHeap::HAS_FORWARDED_BITPOS);
__ bnez(tmp1, L_skip);
}
// Make sure klass is 'reasonable', which is not zero.
__ load_narrow_klass(tmp1, obj);
__ beqz(tmp1, L_error);
__ bind(L_skip);
}
void ShenandoahBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
Register start, Register count, Register tmp) {
assert(ShenandoahCardBarrier, "Did you mean to enable ShenandoahCardBarrier?");
@ -471,74 +497,39 @@ void ShenandoahBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssemb
#define __ ce->masm()->
void ShenandoahBarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub) {
ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
// At this point we know that marking is in progress.
// If do_load() is true then we have to emit the
// load of the previous value; otherwise it has already
// been loaded into _pre_val.
void ShenandoahBarrierSetAssembler::keepalive_barrier_c1_stub(LIR_Assembler* ce, ShenandoahKeepaliveBarrierStub* stub) {
__ bind(*stub->entry());
assert(stub->pre_val()->is_register(), "Precondition.");
ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
Register pre_val_reg = stub->pre_val()->as_register();
Register obj = stub->obj()->as_register();
if (stub->do_load()) {
ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /* wide */);
ce->mem2reg(stub->addr(), stub->obj(), T_OBJECT, lir_patch_none, nullptr, false /* wide */);
}
__ beqz(pre_val_reg, *stub->continuation(), /* is_far */ true);
ce->store_parameter(stub->pre_val()->as_register(), 0);
__ far_call(RuntimeAddress(bs->pre_barrier_c1_runtime_code_blob()->code_begin()));
__ beqz(obj, *stub->continuation(), /* is_far */ true);
ce->store_parameter(obj, 0);
__ far_call(RuntimeAddress(bs->keepalive_barrier_stub()));
__ j(*stub->continuation());
}
void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assembler* ce,
ShenandoahLoadReferenceBarrierStub* stub) {
ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
void ShenandoahBarrierSetAssembler::load_reference_barrier_c1_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub) {
__ bind(*stub->entry());
DecoratorSet decorators = stub->decorators();
bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators);
bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators);
bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators);
bool is_native = ShenandoahBarrierSet::is_native_access(decorators);
ShenandoahBarrierSetC1* bs = (ShenandoahBarrierSetC1*) BarrierSet::barrier_set()->barrier_set_c1();
Register obj = stub->obj()->as_register();
Register res = stub->result()->as_register();
Register addr = stub->addr()->as_pointer_register();
Register tmp1 = stub->tmp1()->as_register();
Register tmp2 = stub->tmp2()->as_register();
Register slow_result = stub->slow_result()->as_register();
assert_different_registers(obj, addr, slow_result);
assert(slow_result == x10, "C1 must know about our slow call result register");
assert(res == x10, "result must arrive in x10");
assert_different_registers(tmp1, tmp2, t0);
if (res != obj) {
__ mv(res, obj);
}
if (is_strong) {
// Check for object in cset.
__ mv(tmp2, ShenandoahHeap::in_cset_fast_test_addr());
__ srli(tmp1, res, ShenandoahHeapRegion::region_size_bytes_shift_jint());
__ add(tmp2, tmp2, tmp1);
__ lbu(tmp2, Address(tmp2));
__ beqz(tmp2, *stub->continuation(), true /* is_far */);
}
ce->store_parameter(res, 0);
ce->store_parameter(obj, 0);
ce->store_parameter(addr, 1);
if (is_strong) {
if (is_native) {
__ far_call(RuntimeAddress(bs->load_reference_barrier_strong_native_rt_code_blob()->code_begin()));
} else {
__ far_call(RuntimeAddress(bs->load_reference_barrier_strong_rt_code_blob()->code_begin()));
}
} else if (is_weak) {
__ far_call(RuntimeAddress(bs->load_reference_barrier_weak_rt_code_blob()->code_begin()));
} else {
assert(is_phantom, "only remaining strength");
__ far_call(RuntimeAddress(bs->load_reference_barrier_phantom_rt_code_blob()->code_begin()));
__ far_call(RuntimeAddress(bs->load_reference_barrier_stub(stub->decorators())));
if (obj != slow_result) {
__ mv(obj, slow_result);
}
__ j(*stub->continuation());
@ -548,92 +539,27 @@ void ShenandoahBarrierSetAssembler::gen_load_reference_barrier_stub(LIR_Assemble
#define __ sasm->
void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
__ prologue("shenandoah_pre_barrier", false);
// arg0 : previous value of memory
BarrierSet* bs = BarrierSet::barrier_set();
const Register pre_val = x10;
const Register thread = xthread;
const Register tmp = t0;
Address queue_index(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset()));
Address buffer(thread, in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset()));
Label done;
Label runtime;
// Is marking still active?
Address gc_state(thread, in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
__ lb(tmp, gc_state);
__ test_bit(tmp, tmp, ShenandoahHeap::MARKING_BITPOS);
__ beqz(tmp, done);
// Can we store original value in the thread's buffer?
__ ld(tmp, queue_index);
__ beqz(tmp, runtime);
__ subi(tmp, tmp, wordSize);
__ sd(tmp, queue_index);
__ ld(t1, buffer);
__ add(tmp, tmp, t1);
__ load_parameter(0, t1);
__ sd(t1, Address(tmp, 0));
__ j(done);
__ bind(runtime);
__ push_call_clobbered_registers();
__ load_parameter(0, pre_val);
__ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_barrier_pre), pre_val);
__ pop_call_clobbered_registers();
__ bind(done);
void ShenandoahBarrierSetAssembler::keepalive_barrier_c1_runtime_stub(StubAssembler* sasm) {
__ prologue("shenandoah_keepalive_barrier", false);
const Register tmp_obj = x10;
const Register tmp1 = x11;
const Register tmp2 = x12;
__ push_reg(RegSet::of(tmp1, tmp2, tmp_obj), sp);
__ load_parameter(0, tmp_obj);
satb_barrier(sasm, noreg, tmp_obj, xthread, tmp1, tmp2);
__ pop_reg(RegSet::of(tmp1, tmp2, tmp_obj), sp);
__ epilogue();
}
void ShenandoahBarrierSetAssembler::generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm,
DecoratorSet decorators) {
void ShenandoahBarrierSetAssembler::load_reference_barrier_c1_runtime_stub(StubAssembler* sasm, DecoratorSet decorators) {
__ prologue("shenandoah_load_reference_barrier", false);
// arg0 : object to be resolved
__ push_call_clobbered_registers();
__ load_parameter(0, x10);
__ load_parameter(1, x11);
bool is_strong = ShenandoahBarrierSet::is_strong_access(decorators);
bool is_weak = ShenandoahBarrierSet::is_weak_access(decorators);
bool is_phantom = ShenandoahBarrierSet::is_phantom_access(decorators);
bool is_native = ShenandoahBarrierSet::is_native_access(decorators);
address target = nullptr;
if (is_strong) {
if (is_native) {
target = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong);
} else {
if (UseCompressedOops) {
target = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong_narrow);
} else {
target = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_strong);
}
}
} else if (is_weak) {
assert(!is_native, "weak must not be called off-heap");
if (UseCompressedOops) {
target = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak_narrow);
} else {
target = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_weak);
}
} else {
assert(is_phantom, "only remaining strength");
assert(is_native, "phantom must only be called off-heap");
target = CAST_FROM_FN_PTR(address, ShenandoahRuntime::load_reference_barrier_phantom);
}
__ rt_call(target);
__ mv(t0, x10);
__ pop_call_clobbered_registers();
__ mv(x10, t0);
const Register tmp_obj = x10;
const Register tmp_addr = x11;
__ push_reg(RegSet::of(tmp_addr), sp);
__ load_parameter(0, tmp_obj);
__ load_parameter(1, tmp_addr);
load_reference_barrier(sasm, tmp_obj, Address(tmp_addr, 0), decorators);
__ pop_reg(RegSet::of(tmp_addr), sp);
__ epilogue();
}

View File

@ -33,7 +33,7 @@
#ifdef COMPILER1
class LIR_Assembler;
class ShenandoahPreBarrierStub;
class ShenandoahKeepaliveBarrierStub;
class ShenandoahLoadReferenceBarrierStub;
class StubAssembler;
#endif
@ -79,12 +79,14 @@ public:
Register obj, Register tmp, Label& slowpath);
virtual void try_peek_weak_handle_in_nmethod(MacroAssembler* masm, Register weak_handle, Register obj,
Register tmp, Label& slow_path);
virtual void check_oop(MacroAssembler* masm, Register obj, Register tmp1, Register tmp2, Label& L_error);
#ifdef COMPILER1
void gen_pre_barrier_stub(LIR_Assembler* ce, ShenandoahPreBarrierStub* stub);
void gen_load_reference_barrier_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
void generate_c1_load_reference_barrier_runtime_stub(StubAssembler* sasm, DecoratorSet decorators);
void keepalive_barrier_c1_stub(LIR_Assembler* ce, ShenandoahKeepaliveBarrierStub* stub);
void keepalive_barrier_c1_runtime_stub(StubAssembler* sasm);
void load_reference_barrier_c1_stub(LIR_Assembler* ce, ShenandoahLoadReferenceBarrierStub* stub);
void load_reference_barrier_c1_runtime_stub(StubAssembler* sasm, DecoratorSet decorators);
#endif
#ifdef COMPILER2

View File

@ -1039,7 +1039,7 @@ void ZBarrierSetAssembler::check_oop(MacroAssembler* masm, Register obj, Registe
__ bind(check_oop);
// Make sure klass is 'reasonable', which is not zero
__ load_klass(tmp1, obj, tmp2);
__ load_narrow_klass(tmp1, obj);
__ beqz(tmp1, error);
__ bind(check_zaddress);

View File

@ -103,7 +103,7 @@ define_pd_global(intx, InlineSmallCode, 1000);
product(bool, UseZbb, false, DIAGNOSTIC, "Use Zbb instructions") \
product(bool, UseZbkb, false, EXPERIMENTAL, "Use Zbkb instructions") \
product(bool, UseZbs, false, DIAGNOSTIC, "Use Zbs instructions") \
product(bool, UseZfa, false, EXPERIMENTAL, "Use Zfa instructions") \
product(bool, UseZfa, false, DIAGNOSTIC, "Use Zfa instructions") \
product(bool, UseZfh, false, DIAGNOSTIC, "Use Zfh instructions") \
product(bool, UseZfhmin, false, DIAGNOSTIC, "Use Zfhmin instructions") \
product(bool, UseZacas, false, EXPERIMENTAL, "Use Zacas instructions") \
@ -117,9 +117,10 @@ define_pd_global(intx, InlineSmallCode, 1000);
product(bool, UseZihintpause, false, EXPERIMENTAL, \
"Use Zihintpause instructions") \
product(bool, UseZtso, false, EXPERIMENTAL, "Assume Ztso memory model") \
product(bool, UseZvbb, false, EXPERIMENTAL, "Use Zvbb instructions") \
product(bool, UseZvbb, false, DIAGNOSTIC, "Use Zvbb instructions") \
product(bool, UseZvbc, false, EXPERIMENTAL, "Use Zvbc instructions") \
product(bool, UseZvfh, false, DIAGNOSTIC, "Use Zvfh instructions") \
product(bool, UseZvfhmin, false, DIAGNOSTIC, "Use Zvfhmin instructions") \
product(bool, UseZvkg, false, DIAGNOSTIC, "Use Zvkg instructions") \
product(bool, UseZvkn, false, DIAGNOSTIC, \
"Use Zvkn group extension, Zvkned, Zvknhb, Zvkb, Zvkt") \

View File

@ -3767,16 +3767,19 @@ void MacroAssembler::load_narrow_klass_compact(Register dst, Register src) {
srli(dst, dst, markWord::klass_shift);
}
void MacroAssembler::load_narrow_klass(Register dst, Register src) {
if (UseCompactObjectHeaders) {
load_narrow_klass_compact(dst, src);
} else {
lwu(dst, Address(src, oopDesc::klass_offset_in_bytes()));
}
}
void MacroAssembler::load_klass(Register dst, Register src, Register tmp) {
assert_different_registers(dst, tmp);
assert_different_registers(src, tmp);
if (UseCompactObjectHeaders) {
load_narrow_klass_compact(dst, src);
decode_klass_not_null(dst, tmp);
} else {
lwu(dst, Address(src, oopDesc::klass_offset_in_bytes()));
decode_klass_not_null(dst, tmp);
}
load_narrow_klass(dst, src);
decode_klass_not_null(dst, tmp);
}
void MacroAssembler::store_klass(Register dst, Register src, Register tmp) {

View File

@ -197,6 +197,7 @@ class MacroAssembler: public Assembler {
Register val, Register tmp1, Register tmp2, Register tmp3);
void load_klass(Register dst, Register src, Register tmp = t0);
void load_narrow_klass_compact(Register dst, Register src);
void load_narrow_klass(Register dst, Register src);
void store_klass(Register dst, Register src, Register tmp = t0);
void cmp_klass_beq(Register obj, Register klass,
Register tmp1, Register tmp2,

View File

@ -1105,8 +1105,9 @@ void reg_mask_init() {
_NO_SPECIAL_PTR_REG_mask.assignFrom(_ALL_REG_mask);
_NO_SPECIAL_PTR_REG_mask.subtract(_NON_ALLOCATABLE_REG_mask);
// x27 is not allocatable when compressed oops is on
if (UseCompressedOops) {
// x27 is not allocatable when compressed oops is on and heapbase is not zero,
// compressed klass pointers doesn't use x27 when heapbase is zero.
if (UseCompressedOops && (CompressedOops::base() != nullptr)) {
_NO_SPECIAL_REG32_mask.remove(OptoReg::as_OptoReg(x27->as_VMReg()));
_NO_SPECIAL_REG_mask.remove(OptoReg::as_OptoReg(x27->as_VMReg()));
_NO_SPECIAL_PTR_REG_mask.remove(OptoReg::as_OptoReg(x27->as_VMReg()));
@ -2100,25 +2101,25 @@ uint Matcher::float_pressure_limit()
return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.size() : FLOATPRESSURE;
}
const RegMask& Matcher::divI_proj_mask() {
const RegMask& Matcher::firstI_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}
// Register for MODI projection of divmodI.
const RegMask& Matcher::modI_proj_mask() {
// Register for the second projection of an int pair
const RegMask& Matcher::secondI_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}
// Register for DIVL projection of divmodL.
const RegMask& Matcher::divL_proj_mask() {
// Register for the first projection of a long pair
const RegMask& Matcher::firstL_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}
// Register for MODL projection of divmodL.
const RegMask& Matcher::modL_proj_mask() {
// Register for the second projection of a long pair
const RegMask& Matcher::secondL_proj_mask() {
ShouldNotReachHere();
return RegMask::EMPTY;
}

View File

@ -113,6 +113,7 @@ source %{
break;
case Op_VectorCastHF2F:
case Op_VectorCastF2HF:
return UseZvfh || UseZvfhmin;
case Op_AddVHF:
case Op_SubVHF:
case Op_MulVHF:

View File

@ -1889,7 +1889,7 @@ class StubGenerator: public StubCodeGenerator {
__ sext(scratch_length, length, 32); // length (elements count, 32-bits value)
__ bltz(scratch_length, L_failed);
__ load_klass(scratch_src_klass, src);
__ load_narrow_klass(scratch_src_klass, src);
#ifdef ASSERT
{
BLOCK_COMMENT("assert klasses not null {");
@ -1898,11 +1898,12 @@ class StubGenerator: public StubCodeGenerator {
__ bind(L1);
__ stop("broken null klass");
__ bind(L2);
__ load_klass(t0, dst, t1);
__ load_narrow_klass(t0, dst);
__ beqz(t0, L1); // this would be broken also
BLOCK_COMMENT("} assert klasses not null done");
}
#endif
__ decode_klass_not_null(scratch_src_klass, t0);
// Load layout helper (32-bits)
//

View File

@ -219,78 +219,80 @@ class VM_Version : public Abstract_VM_Version {
//
// Fields description in `decl`:
// declaration name, extension name, bit value from linux, feature string?, mapped flag)
#define RV_EXT_FEATURE_FLAGS(decl) \
/* A Atomic Instructions */ \
decl(a , ('A' - 'A'), true , NO_UPDATE_DEFAULT) \
/* C Compressed Instructions */ \
decl(c , ('C' - 'A'), true , UPDATE_DEFAULT(UseRVC)) \
/* D Single-Precision Floating-Point */ \
decl(d , ('D' - 'A'), true , NO_UPDATE_DEFAULT) \
/* F Single-Precision Floating-Point */ \
decl(f , ('F' - 'A'), true , NO_UPDATE_DEFAULT) \
/* H Hypervisor */ \
decl(h , ('H' - 'A'), true , NO_UPDATE_DEFAULT) \
/* I RV64I */ \
decl(i , ('I' - 'A'), true , NO_UPDATE_DEFAULT) \
/* M Integer Multiplication and Division */ \
decl(m , ('M' - 'A'), true , NO_UPDATE_DEFAULT) \
/* Q Quad-Precision Floating-Point */ \
decl(q , ('Q' - 'A'), true , NO_UPDATE_DEFAULT) \
/* V Vector */ \
decl(v , ('V' - 'A'), true , UPDATE_DEFAULT(UseRVV)) \
\
/* ----------------------- Other extensions ----------------------- */ \
\
/* Atomic compare-and-swap (CAS) instructions */ \
decl(Zacas , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \
/* Zba Address generation instructions */ \
decl(Zba , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZba)) \
/* Zbb Basic bit-manipulation */ \
decl(Zbb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \
/* Zbc Carry-less multiplication */ \
decl(Zbc , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
/* Bitmanip instructions for Cryptography */ \
decl(Zbkb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbkb)) \
/* Zbs Single-bit instructions */ \
decl(Zbs , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \
/* Zcb Simple code-size saving instructions */ \
decl(Zcb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZcb)) \
/* Additional Floating-Point instructions */ \
decl(Zfa , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfa)) \
/* Zfh Half-Precision Floating-Point instructions */ \
decl(Zfh , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfh)) \
/* Zfhmin Minimal Half-Precision Floating-Point instructions */ \
decl(Zfhmin , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfhmin)) \
/* Zicbom Cache Block Management Operations */ \
decl(Zicbom , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbom)) \
/* Zicbop Cache Block Prefetch Operations */ \
decl(Zicbop , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbop)) \
/* Zicboz Cache Block Zero Operations */ \
decl(Zicboz , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicboz)) \
/* Base Counters and Timers */ \
decl(Zicntr , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
/* Zicond Conditional operations */ \
decl(Zicond , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicond)) \
/* Zicsr Control and Status Register (CSR) Instructions */ \
decl(Zicsr , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
/* Zic64b Cache blocks must be 64 bytes in size, naturally aligned in the address space. */ \
decl(Zic64b , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \
/* Zifencei Instruction-Fetch Fence */ \
decl(Zifencei , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
/* Zihintpause Pause instruction HINT */ \
decl(Zihintpause , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \
/* Total Store Ordering */ \
decl(Ztso , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \
/* Vector Basic Bit-manipulation */ \
decl(Zvbb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbb, &ext_v, nullptr)) \
/* Vector Carryless Multiplication */ \
decl(Zvbc , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbc, &ext_v, nullptr)) \
/* Vector Extension for Half-Precision Floating-Point */ \
decl(Zvfh , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvfh, &ext_v, &ext_Zfh, nullptr)) \
/* Shorthand for Zvkned + Zvknhb + Zvkb + Zvkt */ \
decl(Zvkn , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkn, &ext_v, nullptr)) \
/* Zvkg crypto extension for ghash and gcm */ \
decl(Zvkg , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkg, &ext_v, nullptr)) \
#define RV_EXT_FEATURE_FLAGS(decl) \
/* A Atomic Instructions */ \
decl(a , ('A' - 'A'), true , NO_UPDATE_DEFAULT) \
/* C Compressed Instructions */ \
decl(c , ('C' - 'A'), true , UPDATE_DEFAULT(UseRVC)) \
/* D Single-Precision Floating-Point */ \
decl(d , ('D' - 'A'), true , NO_UPDATE_DEFAULT) \
/* F Single-Precision Floating-Point */ \
decl(f , ('F' - 'A'), true , NO_UPDATE_DEFAULT) \
/* H Hypervisor */ \
decl(h , ('H' - 'A'), true , NO_UPDATE_DEFAULT) \
/* I RV64I */ \
decl(i , ('I' - 'A'), true , NO_UPDATE_DEFAULT) \
/* M Integer Multiplication and Division */ \
decl(m , ('M' - 'A'), true , NO_UPDATE_DEFAULT) \
/* Q Quad-Precision Floating-Point */ \
decl(q , ('Q' - 'A'), true , NO_UPDATE_DEFAULT) \
/* V Vector */ \
decl(v , ('V' - 'A'), true , UPDATE_DEFAULT(UseRVV)) \
\
/* ----------------------- Other extensions ----------------------- */ \
\
/* Atomic compare-and-swap (CAS) instructions */ \
decl(Zacas , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \
/* Zba Address generation instructions */ \
decl(Zba , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZba)) \
/* Zbb Basic bit-manipulation */ \
decl(Zbb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \
/* Zbc Carry-less multiplication */ \
decl(Zbc , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
/* Bitmanip instructions for Cryptography */ \
decl(Zbkb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbkb)) \
/* Zbs Single-bit instructions */ \
decl(Zbs , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \
/* Zcb Simple code-size saving instructions */ \
decl(Zcb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZcb)) \
/* Additional Floating-Point instructions */ \
decl(Zfa , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfa)) \
/* Zfh Half-Precision Floating-Point instructions */ \
decl(Zfh , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfh)) \
/* Zfhmin Minimal Half-Precision Floating-Point instructions */ \
decl(Zfhmin , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfhmin)) \
/* Zicbom Cache Block Management Operations */ \
decl(Zicbom , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbom)) \
/* Zicbop Cache Block Prefetch Operations */ \
decl(Zicbop , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbop)) \
/* Zicboz Cache Block Zero Operations */ \
decl(Zicboz , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicboz)) \
/* Base Counters and Timers */ \
decl(Zicntr , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
/* Zicond Conditional operations */ \
decl(Zicond , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicond)) \
/* Zicsr Control and Status Register (CSR) Instructions */ \
decl(Zicsr , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
/* Zic64b Cache blocks must be 64 bytes in size, naturally aligned in the address space. */ \
decl(Zic64b , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \
/* Zifencei Instruction-Fetch Fence */ \
decl(Zifencei , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
/* Zihintpause Pause instruction HINT */ \
decl(Zihintpause , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \
/* Total Store Ordering */ \
decl(Ztso , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \
/* Vector Basic Bit-manipulation */ \
decl(Zvbb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbb, &ext_v, nullptr)) \
/* Vector Carryless Multiplication */ \
decl(Zvbc , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbc, &ext_v, nullptr)) \
/* Vector Extension for Half-Precision Floating-Point */ \
decl(Zvfh , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvfh, &ext_v, &ext_Zfhmin, nullptr)) \
/* Vector Extension for Minimal Half-Precision Floating-Point */ \
decl(Zvfhmin , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvfhmin, &ext_v, nullptr)) \
/* Shorthand for Zvkned + Zvknhb + Zvkb + Zvkt */ \
decl(Zvkn , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkn, &ext_v, nullptr)) \
/* Zvkg crypto extension for ghash and gcm */ \
decl(Zvkg , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkg, &ext_v, nullptr)) \
#define DECLARE_RV_EXT_FEATURE(PRETTY, LINUX_BIT, FSTRING, FLAGF) \
struct ext_##PRETTY##RVExtFeatureValue : public RVExtFeatureValue { \
@ -442,6 +444,7 @@ private:
RV_ENABLE_EXTENSION(UseZicboz) \
RV_ENABLE_EXTENSION(UseZicond) \
RV_ENABLE_EXTENSION(UseZihintpause) \
RV_ENABLE_EXTENSION(UseZvfhmin) \
static void useRVA23U64Profile();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2026, 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.
*
@ -197,8 +197,10 @@ void AbstractInterpreter::layout_activation(Method* method,
assert(is_bottom_frame && (sender_sp == caller->unextended_sp()),
"must initialize sender_sp of bottom skeleton frame when pushing it");
} else {
assert(caller->is_entry_frame() || caller->is_upcall_stub_frame(), "is there a new frame type??");
sender_sp = caller->sp(); // Call_stub only uses it's fp.
// For entry, upcall_stub, and native frames, sender_sp is simply the caller's sp.
// These frames use the standard C ABI and don't require adjustment.
assert(caller->is_entry_frame() || caller->is_upcall_stub_frame() || caller->is_native_frame(), "is there a new frame type??");
sender_sp = caller->sp();
}
interpreter_frame->interpreter_frame_set_method(method);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2024 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -3279,6 +3279,9 @@ class Assembler : public AbstractAssembler {
static bool is_z_nop(address x) {
return is_z_nop(* (short *) x);
}
static bool is_z_illtrap(address x) {
return *(uint8_t*)x == 0u;
}
static bool is_z_br(long x) {
return is_z_bcr(x) && ((x & 0x00f0) == 0x00f0);
}

View File

@ -524,6 +524,7 @@ void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) {
__ z_nop();
__ z_brasl(Z_R14, op->addr());
add_call_info(code_offset(), op->info());
__ post_call_nop();
}
void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
@ -539,7 +540,7 @@ void LIR_Assembler::ic_call(LIR_OpJavaCall* op) {
// CALL to fixup routine. Fixup routine uses ScopeDesc info
// to determine who we intended to call.
__ relocate(virtual_call_Relocation::spec(virtual_call_oop_addr));
call(op, relocInfo::none);
call(op, relocInfo::none); // call will emit a post call nop, see above method.
}
void LIR_Assembler::move_regs(Register from_reg, Register to_reg) {
@ -2413,32 +2414,9 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {
}
void LIR_Assembler::type_profile_helper(Register mdo, ciMethodData *md, ciProfileData *data,
Register recv, Register tmp1, Label* update_done) {
uint i;
for (i = 0; i < VirtualCallData::row_limit(); i++) {
Label next_test;
// See if the receiver is receiver[n].
Address receiver_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)));
__ z_cg(recv, receiver_addr);
__ z_brne(next_test);
Address data_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i)));
__ add2mem_64(data_addr, DataLayout::counter_increment, tmp1);
__ branch_optimized(Assembler::bcondAlways, *update_done);
__ bind(next_test);
}
// Didn't find receiver; find next empty slot and fill it in.
for (i = 0; i < VirtualCallData::row_limit(); i++) {
Label next_test;
Address recv_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)));
__ z_ltg(Z_R0_scratch, recv_addr);
__ z_brne(next_test);
__ z_stg(recv, recv_addr);
__ load_const_optimized(tmp1, DataLayout::counter_increment);
__ z_stg(tmp1, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i)), mdo);
__ branch_optimized(Assembler::bcondAlways, *update_done);
__ bind(next_test);
}
Register recv, Register tmp1) {
int mdp_offset = md->byte_offset_of_slot(data, in_ByteSize(0));
__ profile_receiver_type(recv, mdo, mdp_offset, tmp1);
}
void LIR_Assembler::setup_md_access(ciMethod* method, int bci,
@ -2510,13 +2488,9 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L
__ branch_optimized(Assembler::bcondAlways, *obj_is_null);
__ bind(not_null);
NearLabel update_done;
Register recv = k_RInfo;
__ load_klass(recv, obj);
type_profile_helper(mdo, md, data, recv, Rtmp1, &update_done);
Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()));
__ add2mem_64(counter_addr, DataLayout::counter_increment, Rtmp1);
__ bind(update_done);
type_profile_helper(mdo, md, data, recv, Rtmp1);
} else {
__ compareU64_and_branch(obj, (intptr_t) 0, Assembler::bcondEqual, *obj_is_null);
}
@ -2606,13 +2580,9 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {
__ branch_optimized(Assembler::bcondAlways, done);
__ bind(not_null);
NearLabel update_done;
Register recv = k_RInfo;
__ load_klass(recv, value);
type_profile_helper(mdo, md, data, recv, Rtmp1, &update_done);
Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()));
__ add2mem_64(counter_addr, DataLayout::counter_increment, Rtmp1);
__ bind(update_done);
type_profile_helper(mdo, md, data, recv, Rtmp1);
} else {
__ compareU64_and_branch(value, (intptr_t) 0, Assembler::bcondEqual, done);
}
@ -2772,11 +2742,8 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
// statically update the MethodData* rather than needing to do
// dynamic tests on the receiver type.
// NOTE: we should probably put a lock around this search to
// avoid collisions by concurrent compilations.
ciVirtualCallData* vc_data = (ciVirtualCallData*) data;
uint i;
for (i = 0; i < VirtualCallData::row_limit(); i++) {
for (uint i = 0; i < VirtualCallData::row_limit(); i++) {
ciKlass* receiver = vc_data->receiver(i);
if (known_klass->equals(receiver)) {
Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)));
@ -2784,32 +2751,13 @@ void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {
return;
}
}
// Receiver type not found in profile data. Select an empty slot.
// Note that this is less efficient than it should be because it
// always does a write to the receiver part of the
// VirtualCallData rather than just the first time.
for (i = 0; i < VirtualCallData::row_limit(); i++) {
ciKlass* receiver = vc_data->receiver(i);
if (receiver == nullptr) {
Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)));
metadata2reg(known_klass->constant_encoding(), tmp1);
__ z_stg(tmp1, recv_addr);
Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)));
__ add2mem_64(data_addr, DataLayout::counter_increment, tmp1);
return;
}
}
// Receiver type is not found in profile data.
// Fall back to runtime helper to handle the rest at runtime.
metadata2reg(known_klass->constant_encoding(), recv);
} else {
__ load_klass(recv, recv);
NearLabel update_done;
type_profile_helper(mdo, md, data, recv, tmp1, &update_done);
// Receiver did not match any saved receiver and there is no empty row for it.
// Increment total counter to indicate polymorphic case.
__ add2mem_64(counter_addr, DataLayout::counter_increment, tmp1);
__ bind(update_done);
}
type_profile_helper(mdo, md, data, recv, tmp1);
} else {
// static call
__ add2mem_64(counter_addr, DataLayout::counter_increment, tmp1);
@ -2845,6 +2793,7 @@ void LIR_Assembler::rt_call(LIR_Opr result, address dest,
if (info != nullptr) {
add_call_info_here(info);
}
__ post_call_nop();
}
void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) {

Some files were not shown because too many files have changed in this diff Show More