mirror of
https://github.com/openjdk/jdk.git
synced 2026-08-04 07:05:31 +00:00
Merge branch 'master' into JDK-8344159
This commit is contained in:
commit
044cfc097d
6
.github/actions/build-jtreg/action.yml
vendored
6
.github/actions/build-jtreg/action.yml
vendored
@ -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
|
||||
|
||||
4
.github/actions/do-build/action.yml
vendored
4
.github/actions/do-build/action.yml
vendored
@ -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'
|
||||
|
||||
2
.github/actions/get-bootjdk/action.yml
vendored
2
.github/actions/get-bootjdk/action.yml
vendored
@ -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 }}
|
||||
|
||||
6
.github/actions/get-bundles/action.yml
vendored
6
.github/actions/get-bundles/action.yml
vendored
@ -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
|
||||
|
||||
2
.github/actions/get-gtest/action.yml
vendored
2
.github/actions/get-gtest/action.yml
vendored
@ -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 }}'
|
||||
|
||||
2
.github/actions/get-jtreg/action.yml
vendored
2
.github/actions/get-jtreg/action.yml
vendored
@ -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
|
||||
|
||||
4
.github/actions/get-msys2/action.yml
vendored
4
.github/actions/get-msys2/action.yml
vendored
@ -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
|
||||
|
||||
2
.github/actions/upload-bundles/action.yml
vendored
2
.github/actions/upload-bundles/action.yml
vendored
@ -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
|
||||
|
||||
2
.github/workflows/build-alpine-linux.yml
vendored
2
.github/workflows/build-alpine-linux.yml
vendored
@ -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: |
|
||||
|
||||
4
.github/workflows/build-cross-compile.yml
vendored
4
.github/workflows/build-cross-compile.yml
vendored
@ -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') }}
|
||||
|
||||
2
.github/workflows/build-linux.yml
vendored
2
.github/workflows/build-linux.yml
vendored
@ -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
|
||||
|
||||
2
.github/workflows/build-macos.yml
vendored
2
.github/workflows/build-macos.yml
vendored
@ -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
|
||||
|
||||
2
.github/workflows/build-windows.yml
vendored
2
.github/workflows/build-windows.yml
vendored
@ -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
|
||||
|
||||
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@ -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
|
||||
|
||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@ -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'
|
||||
|
||||
@ -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,)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
################################################################################
|
||||
|
||||
# Minimum supported versions
|
||||
JTREG_MINIMUM_VERSION=8.2.1
|
||||
JTREG_MINIMUM_VERSION=8.3
|
||||
GTEST_MINIMUM_VERSION=1.14.0
|
||||
|
||||
################################################################################
|
||||
|
||||
@ -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])
|
||||
;;
|
||||
|
||||
@ -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 = \
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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"),
|
||||
|
||||
@ -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 \
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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'
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
################################################################################
|
||||
|
||||
@ -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, \
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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()));
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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',
|
||||
`
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
%}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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 &&
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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()) {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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 __
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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") \
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -113,6 +113,7 @@ source %{
|
||||
break;
|
||||
case Op_VectorCastHF2F:
|
||||
case Op_VectorCastF2HF:
|
||||
return UseZvfh || UseZvfhmin;
|
||||
case Op_AddVHF:
|
||||
case Op_SubVHF:
|
||||
case Op_MulVHF:
|
||||
|
||||
@ -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)
|
||||
//
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user